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

使用awk将单个列转换为三个逗号分隔的列,awk,Awk,我有一个长列,希望使用awk或任何Unix工具将其重新格式化为三个逗号分隔的列,如下所示 输入: Xaa Ybb Mdd Tmmn UUnx THM THSS THEY DDe Xaa,Ybb,Mdd Tmmn,UUnx,THM THSS,THEY,DDe 输出: Xaa Ybb Mdd Tmmn UUnx THM THSS THEY DDe Xaa,Ybb,Mdd Tmmn,UUnx,THM THSS,THEY,DDe 工作原理 对于每一行输入,这会根据行号打印行后接逗号或换行符 关键

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

输入:

Xaa
Ybb
Mdd
Tmmn
UUnx
THM
THSS
THEY
DDe
Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe
输出:

Xaa
Ybb
Mdd
Tmmn
UUnx
THM
THSS
THEY
DDe
Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe
工作原理 对于每一行输入,这会根据行号打印行后接逗号或换行符

关键部分是这一三元陈述:

NR%3?",":"\n"
这取3模的行号。如果该值不为零,则返回一个逗号。如果为零,则返回换行符

处理在最后一行完成之前结束的文件 假定文件中的行数是三的整数倍。如果不是,那么我们可能希望确保最后一行有一个换行符。正如Jonathan Leffler所建议的,这可以通过以下方式实现:

awk '{printf "%s%s",$0,NR%3?",":"\n";} END { if (NR%3 != 0) print ""}' file
如果最后一行缺少三列,上面的代码将在该行留下一个逗号。这可能是问题,也可能不是问题。如果不需要最后一个逗号,请使用:

awk 'NR==1{printf "%s",$0; next} {printf "%s%s",(NR-1)%3?",":"\n",$0;} END {print ""}' file
Jonathan Leffler提供了这个稍微简单的替代方案,以实现相同的目标:

awk '{ printf("%s%s", pad, $1); pad = (NR%3 == 0) ? "\n" : "," } END { print "" }'
改进的可移植性 为了支持不使用
\n
作为线路终端的平台,Ed Morton建议:

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

这有一个工具。使用
pr

pr -3ats,

3列宽度,跨距,抑制标题,逗号作为分隔符。

添加
END{if(NR%3!=0)print”“}是否有任何优点
以便在输入中没有三行的倍数时,最后一行至少以换行结束?修复它以使您不发出额外的尾随逗号更难(也就是说,如果文件长度不是三行的倍数,您可能会有最后一行读取
One、
One、Two、
。@JonathanLeffler好主意!我把你的建议加到了答案上。我还添加了代码以省略最后一个逗号。有趣的是,当您的注释弹出时,我正在进行实验,我想到了:
awk'{printf(“%s%s”,pad,$1);pad=(NR%3==0)?“\n:”,“}END{print”“}”
。这使用了“未初始化变量被视为空字符串”属性。而且,
print
总是输出一个换行符(我尝试了
print“\n”
,它在末尾给出了两个换行符;
printf“\n”
可以代替
print”“
)。这是正确的方法,所以
+1
,但有两点-1)你应该使用
OR
,而不是
“\n”
因此,即使在换行符为
\r\n
的平台/应用程序上,它也能工作(而且更简洁),2)在某些上下文中,未细化的三元表达式会在某些awk中导致语法错误(例如,在OSX awk上尝试
打印1>2?:foo:“bar”
),因此最好总是将其括起来
(NR%3?,“:ORS)
甚至
-v of s=。。。(NR%3?OFS:ORS)
以避免该问题,并且当三元表达式的开始/结束被这样分隔时,它会稍微提高清晰度。@EdMorton太棒了!补充到答案中。
pr -3ats,