我有一个文件,有一个整数列表:
12542 58696 78845 87855 ...
我想把它们改成:
"12542", "58696", "78845", "87855", "..."
(最后没有逗号)
我相信我需要使用sed,但无法弄清楚如何。 感谢你的帮助。
你可以做一个sed多行技巧,但最简单的方法是利用shell扩展:
echo $(sed '$ ! s/.*/"&",/; $ s/.*/"&"/' foo.txt)
运行echo $(cat file)
,看看为什么这个工程。 简而言之,诀窍是猫的结果被解析成标记,并被解释为独立的参数echo
,打印它们以空格分隔。
sed表达式读取
$ ! s/.*/"&",/ $ s/.*/"&"/
…这意味着:除了最后一行( $ !
)之外的所有行都用"line",
替换,最后一行用"line"
替换。
编辑:如果该文件不仅包含像在OP的情况下(当文件可以包含字符外壳扩展)的一行整数,下面的工作:
编辑2:一般情况下更好的代码。
sed -n 's/.*/"&"/; $! s/$/,/; 1 h; 1 ! H; $ { x; s/\n/ /g; p; }' foo.txt
说明:以更易读的方式编写,sed脚本是
s/.*/"&"/ $! s/$/,/ 1 h 1! H $ { x s/\n/ /g p }
这意味着什么:
s/.*/"&"/
用双引号把每一行都包起来。
$! s/$/,/
如果不是最后一行,请附加逗号
1 h 1! H
如果是第一行,则用上一次转换的结果覆盖保持缓冲区,否则将其附加到保持缓冲区。
$ { x s/\n/ /g p }
如果它是最后一行 – 在这一点上,保持缓冲区包含整行用双引号用逗号适当地将保持缓冲区与模式空间交换,用空格替换换行符并打印结果。
用perl没有任何管道/叉子:
perl -0ne 'print join(", ", map { "\042$_\042" } split), "\n"' file
"12542", "58696", "78845", "87855"
这是一个纯粹的Bash(Bash≥4)可能性,它读取内存中的整个文件,所以对于大文件来说不会有好处:
mapfile -t ary < file ((${#ary[@]})) && printf '"%s"' "${ary[0]}" ((${#ary[@]}>1)) && printf ', "%s"' "${ary[@]:1}" printf '\n'
对于大文件,这个awk
似乎可以(而且会很快):
awk '{if(NR>1) printf ", ";printf("\"%s\"",$0)} END {print ""}' file
这是解决方案,
sed 's/.*/ "&"/' input-file|tr '\n' ','|rev | cut -c 2- | rev|sed 's/^.//'
首先用引号改变你的输入文本行
sed 's/.*/ "&"/' input-file
然后,这将把你的新行转换成逗号
tr '\n' ',' <your-inputfile>
包括rev
, cut
和sed
在内的最后一个命令用于根据需要对输出进行格式化。
哪里,
rev
是反转字符串。
cut
正在从输出中删除尾随逗号。
sed
将删除字符串中的第一个字符以相应地进行格式化。
输出:
一种方式,使用sed
:
sed ':a; N; $!ba; s/\n/", "/g; s/.*/"&"/' file
结果:
"12542", "58696", "78845", "87855", "..."
您可以在最后一行没有逗号的情况下将行列值写入,如下所示:
cnt=0 while read -r line || test -n "$line" ; do [ "$cnt" = "0" ] && printf "\"%s\"" "$line" printf ", \"%s\"" "$line" cnt=$((cnt + 1)) done printf "\n"
输出:
$ bash col2row.sh dat/ncol.txt "12542", "12542", "58696", "78845", "87855"
简化的awk
解决方案:
awk '{ printf sep "\"%s\"", $0; sep=", " }' file
sep
)。 sep "\"%s\""
通过连接sep
和\"%s\"
来合成格式化字符串以便与printf
一起使用。 生成的格式字符串应用于$0
,每个输入行。 sep
只在第一个输入记录之后初始化,
所以只能在输出元素之间插入。