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

3

我会尽力为您翻译,您提供的内容是将一个长列重新格式化为三个逗号分隔的列,如下所示,使用 awk 或任何 Unix 工具。

输入:

Xaa
Ybb
Mdd
Tmmn
UUnx
THM
THSS
THEY
DDe

输出:

Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe
3个回答

7
$ awk '{printf "%s%s",$0,NR%3?",":"\n";}' file
Xaa,Ybb,Mdd
Tmmn,UUnx,THM
THSS,THEY,DDe

工作原理

对于每一行输入,这个程序会先输出该行内容,然后根据行号输出逗号或换行符。

其中最关键的部分是三目运算语句:

NR%3?",":"\n"

这将行号模以3。如果结果非零,则返回逗号。如果为零,则返回换行符。

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

假设文件中的行数是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

乔纳森·莱夫勒提供了一个略微简单的替代方案,以实现相同的目标:
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

1
在输入行数不是三的倍数时,添加END { if (NR%3 != 0) print ""}是否有优点,以便至少使最后一行以换行符结束?修复以避免发出额外的尾随逗号更加困难(也就是说,如果文件长度不是三的倍数,则最后一行可能会读取为One,One,Two,)。 - Jonathan Leffler
1
有趣的是,就在你的评论出现时,我正在进行实验,并且我想到了:awk '{ printf("%s%s", pad, $1); pad = (NR%3 == 0) ? "\n" : "," } END { print "" }'。这使用了“未初始化变量被视为空字符串”的属性。而print总是输出一个换行符(我曾经尝试过print "\n",但最后得到了两个换行符;可以用printf "\n"代替print "")。 - Jonathan Leffler
@JonathanLeffler 非常好!我也把那个加到了答案里。 - John1024
2
这是正确的方法,所以 +1,但有几点需要注意 - 1)应该使用 ORS 而不是 "\n",这样它就可以在换行符为 \r\n 的平台/应用程序上工作(而且更简洁),2)在某些 awk 上,未加括号的三元表达式会在某些情况下导致语法错误(例如,在 OSX awk 上尝试 print 1>2?"foo":"bar"),因此最好总是将其括起来 (NR%3?",":ORS),甚至 -v OFS=, ... (NR%3?OFS:ORS),以避免这个问题,并且在我的看法中,当三元表达式的开始/结束被这样分隔时,它可以提高清晰度。 - Ed Morton
1
@EdMorton 很好!已添加到答案中。 - John1024
显示剩余2条评论

3

有一个工具可以做到这一点。使用pr

pr -3ats,

3列宽度,横跨全页,隐藏标题,逗号作为分隔符。

0
xargs -n3 < file | awk -v OFS="," '{$1=$1} 1'

xargs 使用 echo 作为默认操作,$1=$1 强制重建 $0

只使用 awk,我会选择这个(与 @jonathan-leffler 和 @John1024 提出的类似)

{
     sep = NR == 1 ? ""   : \
          (NR-1)%3 ? ","  : \
                     "\n"
     printf sep $0
}

END {
     printf "\n"
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接