我有一个这种形式的输入文件:
foo bar 08 320984 2384
bla foo baz 23 32425 32532
[...]
最后总共有三个令牌,但前面有不明数量的令牌。我想将文件重写为CSV,以便其他应用程序可以自动解析。我当前的awk命令是:
awk '{ print $(NF-2)";"$(NF-1)";"$NF}'
输出应为
foo bar;08;320984;2384
bla foo baz;23;32425;32532
[...]
答案 0 :(得分:2)
不幸的是,awk并不是最伟大的事情(并且cut
能够做到字段范围的能力在这里也没有帮助。
这样的事情应该可行:
awk '{nfff=$(NF-2); nff=$(NF-1); nf=$NF; NF-=3; printf "%s;%s;%s;%s\n", $0, nfff, nff, nf}' file
答案 1 :(得分:1)
如果我理解你和fedorqui:
awk '{for (i=1;i<NF;i++) printf "%s%s",$i,(i+4>NF?";":FS);print $NF}' file
foo bar;08;320984;2384
bla foo baz;23;32425;32532
这会在最后三个字段前添加;
。
John's comment可能是更好的方法。
答案 2 :(得分:1)
sed
也可以运作:
sed 's/\ \([^\ ]\+\)\ \([^\ ]\+\)\ \([^\ ]\+\)$/;\1;\2;\3/' file
或sed
支持-r
:
sed -r 's/\ ([^\ ]+)\ ([^\ ]+)\ ([^\ ]+)$/;\1;\2;\3/' file
它用;
替换最后3个换行符。
或者更容易:
rev file | sed 's/\ /;/g; s/;/\ /g4' | rev
答案 3 :(得分:1)
一种奇特的GNU awk方法:
gawk '
function replace(what) {
return gensub(/[[:blank:]]+([^[:blank:]]+)$/, ";\\1", 1, what)
}
{$0 = replace(replace(replace($0))); print}
' file
foo bar;08;320984;2384
bla foo baz;23;32425;32532
答案 4 :(得分:0)
这应该在最后三个之前的任意数量的字段中执行:
awk '{for (i=1; i <= NF - 3; i++) if (i == 1) printf $i; else printf " "$i} {print ";"$(NF-2)";"$(NF-1)";"$NF}' input
答案 5 :(得分:0)
我是awk的新手,但是这个怎么样(这不会删除空格。):
awk '{for (i=0; i<3; i++) {$(NF-i)=";" $(NF-i)} print $0} ' file
示例:
sdlcb@Goofy-Gen:~/AMD$ cat file
foo bar 08 320984 2384
bla foo baz 23 32425 32532
sdlcb@Goofy-Gen:~/AMD$ awk '{for (i=0; i<3; i++) {$(NF-i)=";" $(NF-i)} print $0} ' file
foo bar ;08 ;320984 ;2384
bla foo baz ;23 ;32425 ;32532