[英]Print a comma except on the last line in Awk
我有以下脚本
awk '{printf "%s", $1"-"$2", "}' $a >> positions;
其中$a
存储文件的名称。 我实际上是将多个列值写入一行。 但是,我想在我不在最后一行时打印一个逗号。
单程方法:
cat "$a" | # look, I can use this in a pipeline!
awk 'NR > 1 { printf(", ") } { printf("%s-%s", $1, $2) }'
请注意,我还简化了字符串格式。
享受这一个:
awk '{printf t $1"-"$2} {t=", "}' $a >> positions
是的,一见钟情看起来有点棘手。 所以,我会解释,首先让我们改变的printf
到print
的清晰度:
awk '{print t $1"-"$2} {t=", "}' file
并查看它的作用,例如,对于具有以下简单内容的文件:
1 A
2 B
3 C
4 D
所以它会产生以下结果:
1-A
, 2-B
, 3-C
, 4-D
诀窍是前面的t
变量,它在开头是空的。 变量将在显示{print t ...}
后的下一步处理中设置{t=...}
{print t ...}
。 因此,如果我们( awk
)继续迭代,我们将获得所需的序列。
我会通过在运行脚本之前查找行数来实现,例如使用coreutils和bash:
awk -v nlines=$(wc -l < $a) '{printf "%s", $1"-"$2} NR != nlines { printf ", " }' $a >>positions
如果您的文件只有2列,则以下coreutils替代方案也可以使用。 示例数据:
paste <(seq 5) <(seq 5 -1 1) | tee testfile
输出:
1 5
2 4
3 3
4 2
5 1
现在用新行替换制表符, paste
可以轻松地将日期组合成所需的格式:
<testfile tr '\t' '\n' | paste -sd-,
输出:
1-5,2-4,3-3,4-2,5-1
您可能认为awk的ORS和OFS是处理此问题的合理方法:
$ awk '{print $1,$2}' OFS="-" ORS=", " input.txt
但这导致最终的ORS,因为输入在最后一行包含换行符。 换行符是一个记录分隔符,因此从awk的角度来看,输入中有一个空的最后一条记录。 你可以通过一些hackery解决这个问题,但由此产生的复杂性消除了单线的优雅。
所以这是我对此的看法。 既然你说你正在“编写多个列值”,那么使用ORS和OFS就可能会导致问题。 所以我们可以完全用格式化来实现所需的输出。
$ cat input.txt
3 2
5 4
1 8
$ awk '{printf "%s%d-%d",t,$1,$2; t=", "} END{print ""}' input.txt
3-2, 5-4, 1-8
这类似于Michael和rook的单遍方法,但它使用单个printf
并正确使用格式字符串进行格式化。
这可能比Michael的解决方案表现得更好,因为分配应该比测试花费更少的CPU,并且明显优于任何多遍解决方案,因为文件只需要读取一次。
这是一种更好的方法,不需要求助于coreutils:
awk 'FNR==NR { c++; next } { ORS = (FNR==c ? "\n" : ", "); print $1, $2 }' OFS="-" file file
awk '{a[NR]=$1"-"$2;next}END{for(i=1;i<NR;i++){print a[i]", " }}' $a > positions
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.