将多行文本转换为以逗号分隔的单行文本

103

我有以下多行数据:

foo
bar
qux
zuu
sdf
sdfasdf

我想做的是将它们转换为一个逗号分隔的行:
foo,bar,qux,zuu,sdf,sdfasdf

最好的Unix单行命令是什么?


如果以下解决方案无法产生所需的结果,例如只显示最后一行的内容,则您的输入中可能存在不需要的控制字符,例如 \r。您可以通过将输入导入到 hdhexdump 中来检查它。\r 会(与 \n 一起)生成两个字节的序列 0a0d。使用 |sed 's/\r//g' 命令进行修复。 - valid
这个问题是一个重复的问题,但并不是所有的答案都是重复的。 - reinierpost
8个回答

178

使用粘贴命令:

paste -d, -s file

3
粘贴是一个很棒的命令。像冠军一样运转! - Ray Hunter
11
但如何对变量或管道执行此操作呢?更新后的命令: 使用不带值的 -s 参数 .... | paste -d, -s - NeoMorfeo
2
虽然这种方法适用于将换行符(\n)转换为逗号的情况,但似乎如果需要将换行符转换为“,”,以满足许多其他命令的要求,则无法使用此方法。 - CoderGuy123
7
你可以使用-字符从管道中读取输入。例如:echo -e "1\n2\n3" | paste -d, -s - - Carson Anderson

92

文件

aaa
bbb
ccc
ddd

xargs

cat file | xargs

结果

aaa bbb ccc ddd 

xargs改进版

cat file | xargs | sed -e 's/ /,/g'

结果

aaa,bbb,ccc,ddd 

1
xargs将多行转换为一行,以空格分隔,然后sed将所有空格替换为逗号(或者如果您使用sed -e 's/ /\ ,/g',则为' ,')(顺便说一句,-e可以省略)。 - Serhii Kuzmychov
通常情况下,xargs 不是为 t 设计的,但它可以工作 :) - Serhii Kuzmychov
而且它更适合日常使用,而不是下面的那个。 - Serhii Kuzmychov
非常感谢您提供逐步操作说明!我的文件每行都只有一个条目(名,姓,ID,状态,空行),我需要将其转换为CSV格式,因此在使用您解释的模块之前,我使用了sed -e 's/^$/#/'命令,将“空行”替换为未使用的符号。 - Bee Kay
我发现这是我正在寻找的解决方案,虽然不是被接受的答案,但它适用于管道和多个文件,并且如果你想添加制表符等,你可以将其传递给tr -s " "\t"。谢谢。 - jimh

12

有很多方法可以实现。你使用的工具主要取决于你自己的偏好或经验。

使用tr命令:

tr '\n' ',' < somefile

使用awk:

awk -F'\n' '{if(NR == 1) {printf $0} else {printf ","$0}}' somefile

1
你的两个命令都会生成结尾逗号。 - Kent
可以,我可以用awk修复它,但不能用tr,给我一分钟。 - n3rV3
2
awk '{printf NR==1?$0:","$0}' file - Chris Seymour
13
如果$0包含任何printf格式字符,则不要使用printf $0,否则会产生难以理解的错误。printf的概要是printf格式,数据,所以应该使用printf“%s”,$0代替。 - Ed Morton
我还有很多需要学习的东西。谢谢 - n3rV3

10

xargs -a your_file | sed 's/ /,/g'

这是一种更简短的方法。


2
除非您的代码行中有空格,否则请返回翻译文本。 - cadrian
sed -e 's/ /+/g' test |xargs|sed 's/ /,/g;s/+/ /g' 这只是一个使用xargs的想法 :) 不要认为它是严肃的 - Serhii Kuzmychov

8
根据您提供的示例,这个awk语句可以工作。(没有尾随逗号)
awk -vRS="" -vOFS=',' '$1=$1' file

测试:

kent$  echo "foo
bar
qux
zuu
sdf
sdfasdf"|awk -vRS="" -vOFS=',' '$1=$1' 
foo,bar,qux,zuu,sdf,sdfasdf

只有在想要在BEGIN块中使用变量时,才需要使用“-v”选项,稍微更简洁的写法是awk '$1=$1' RS= OFS=, file - Chris Seymour
3
为了清晰明了,以免在后续尝试在 BEGIN 块中使用变量时出现意外,我建议始终使用 -v,除非需要在文件间设置不同的变量值。顺便提一下,省略 -v 和变量名之间的空格会使你的脚本过于专注于 gawk,所以我建议使用 -v RS= 而不是 -vRS= - Ed Morton
@EdMorton 感谢您的评论。(在 -v 和 va 之间的“空格”)。我从您那里学到了很多技巧 :)。个人而言,我也总是使用 -v - Kent

6

Perl一行代码:

perl -pe'chomp, s/$/,/ unless eof' file

或者,如果您想更加神秘:
perl '-peeof||chomp&&s/$/,/' file

5
更加简明扼要的翻译:perl '-peeof||s|$/$|,|' file - sid_com
1
sid_com,我喜欢你选择的替换分隔符:D... perl -pe 'eof or s#\n$#,#' thing - protist
好的,更加难懂的 Perl 代码:perl -l54 -pe 'eof and $=""' file(如果你可以忍受最后一个逗号,甚至可以用空的脚本体)。 - Peter K

2
sed -n 's/.*/&,/;H;$x;$s/,\n/,/g;$s/\n\(.*\)/\1/;$s/\(.*\),/\1/;$p'

1
太复杂了。请解释一下 @protist。 - Lazarus Thurston

1
perl -pi.bak -e 'unless(eof){s/\n/,/g}' your_file

这将创建一个带有 .bak 扩展名的原始文件备份,然后修改原始文件。

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