使用awk将单列转换为三个逗号分隔列

ste*_*hen 3 awk

我有一个长列,并希望将其重新格式化为三个逗号分隔列,如下所示,使用awk或任何Unix工具.

输入:

Xaa
Ybb
Mdd
Tmmn
UUnx
THM
THSS
THEY
DDe
Run Code Online (Sandbox Code Playgroud)

输出:

Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe
Run Code Online (Sandbox Code Playgroud)

Joh*_*024 7

$ awk '{printf "%s%s",$0,NR%3?",":"\n";}' file
Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe
Run Code Online (Sandbox Code Playgroud)

这个怎么运作

对于每一行输入,这将打印后面的行,具体取决于行号,逗号或换行符.

关键部分是这个三元声明:

NR%3?",":"\n"
Run Code Online (Sandbox Code Playgroud)

这将采用模数为3的行号.如果它不为零,则返回逗号.如果为零,则返回换行符.

处理在最后一行完成之前结束的文件

假设文件中的行数是三的整数倍.如果不是,那么我们可能想要确保最后一行有换行符.正如Jonathan Leffler建议的那样,这可以通过以下方式完成:

awk '{printf "%s%s",$0,NR%3?",":"\n";} END { if (NR%3 != 0) print ""}' file
Run Code Online (Sandbox Code Playgroud)

如果最后一行缺少三列,则上面的代码将在该行上留下一个逗号.这可能是也可能不是问题.如果我们不想要最终的逗号,那么使用:

awk 'NR==1{printf "%s",$0; next} {printf "%s%s",(NR-1)%3?",":"\n",$0;} END {print ""}' file
Run Code Online (Sandbox Code Playgroud)

Jonathan Leffler提供了这种稍微简单的替代方案来实现相同的目标:

awk '{ printf("%s%s", pad, $1); pad = (NR%3 == 0) ? "\n" : "," } END { print "" }'
Run Code Online (Sandbox Code Playgroud)

提高了可移植性

为了支持不用\n作线路终结器的平台,Ed Morton建议:

awk -v OFS=, '{ printf("%s%s", pad, $1); pad = (NR%3?OFS:ORS)} END { print "" }' file
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的方法,所以`+ 1`但有几点 - 1)你应该使用`ORS`而不是``\n"`所以它甚至可以在换行符为'\ r \'的平台/应用程序上工作n`(并且它稍微简洁一点),2)在某些情况下,一些不明显的三元表达式会导致语法错误(例如在OSX awk上尝试`print 1> 2?"foo":"bar"`所以它是最好总是把它括起来``(NR%3?",":ORS)`或甚至`-v OFS =,...(NR%3?OFS:ORS)`以避免这个问题和恕我直言它提高了清晰度当三元表达式的开始/结束被分隔时. (2认同)