将多行字符串中指定列转换为单个逗号分隔的行

131

假设我有以下字符串:

something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

我该如何将它简化为

+12.0,+15.5,+9.0,+13.5

在bash中怎么做?


2
让我们暂停一下,将这个线程视为对Bash编程语言的明显控诉。考虑Scala的listOfStuff mkString ", ",或者Haskell的intercalate ", " listOfString - F. P. Freely
18个回答

227

简洁明了:

awk '{print $2}' file.txt | paste -s -d, -

8
这是这里最好的答案,显然也是正确的做法。 - forresthopkinsa
1
如何在每个值周围加上单引号/双引号? - Hussain
2
@Hussain cat thing | awk -F',' '{ print "'\''" $7 "'\' '" }' | paste -s -d ',' - starbeamrainbowlabs
真希望我早些知道 paste -s -d',' - ... 我已经使用 blah=$(...|tr '\n' ',');echo "${blah:0:-1}" 或者 Perl 一行命令很长时间了... 这样干净多了。 - zpangwin
更简洁的版本:awk '{print$2}' file.txt | paste -sd, - alephreish
显示剩余2条评论

112

你可以使用 awksed

awk -vORS=, '{ print $2 }' file.txt | sed 's/,$/\n/'

或者如果想使用管道:

echo "data" | awk -vORS=, '{ print $2 }' | sed 's/,$/\n/'

简要概述:

  • awk非常适合处理被分解成字段的数据
  • -vORS=,将“输出记录分隔符”设置为,这正是你想要的
  • { print $2 }告诉awk对于每个记录(行),打印第二个字段
  • file.txt是你的文件名
  • sed只是去掉了尾部的,,并将其转换为换行符(如果你不想要换行符,可以使用s/,$//

1
awk:无效的-v选项 :( - Marsellus Wallace
7
在 macOS 上,给-v和ORS=之间加上一个空格。 - Graham P Heath
如何使用相同的命令获取管道分隔符?awk -v ORS=| '{ print $1 }' DCMC.rtf | sed 's/,$/\n/' 我遇到了一个错误。 - Yogesh D
3
奇怪的是,当我尝试做这件事时,输出为空。 - eternaltyro
1
我认为对于管道版本应该是{print $1},否则输出中只会得到逗号。 - Przemysław Czechowski

27
cat data.txt | xargs | sed -e 's/ /, /g'

我也喜欢这样的解决方案,但是在这里-e参数是否必要,因为只有第一个sed命令被使用?我相信cat data.txt | xargs | sed 's/ /, /g'同样可以工作。例如,echo -e "foo\nbar\nbazz" | xargs | sed 's/ /, /g'输出foo, bar, bazz - John Pancoast

18

这个方法或许适合你:

cut -d' ' -f5 file | paste -d',' -s
+12.0,+15.5,+9.0,+13.5
或者
sed '/^.*\(+[^ ]*\).*/{s//\1/;H};${x;s/\n/,/g;s/.//p};d' file
+12.0,+15.5,+9.0,+13.5
或者
sed 's/\S\+\s\+//;s/\s.*//;H;$!d;x;s/.//;s/\n/,/g' file

对于文件中的每一行,删除第一个字段和其后的空格,删除第二个字段后面的所有内容并附加到 hold space 中。删除除最后一行以外的所有行,在切换到 hold space 后删除引入的换行符,并将所有换行符转换为 ,

注:也可以写成:

sed 's/\S\+\s\+//;s/\s.*//;1h;1!H;$!d;x;s/\n/,/g' file

最优雅的方法是使用 paste!谢谢 - Wojciech Kaczmarek

11

awk一行命令。

$ awk '{printf (NR>1?",":"") $2}' file

+12.0,+15.5,+9.0,+13.5

应该在 printf 后添加格式说明符 "%s",以使其更加健壮,即使它与所有类型的行一起使用,例如 "foo %s"。 - jarno

11
$ awk -v ORS=, '{print $2}' data.txt | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

干杯,假设 AWK 的输入是通过标准输入进行的(在你的示例中只需输入 function | awk...),这该怎么办? - Alex Coplan

8

这也应该可以工作

awk '{print $2}' file | sed ':a;{N;s/\n/,/};ba'

5
尝试这个简单的代码:
awk '{printf("%s,",$2)}' File1

它会添加一个额外的逗号。 - jarno

5
您可以使用 grep 命令:
grep -o "+\S\+" in.txt | tr '\n' ','

该程序查找以+开头的字符串,后跟任何字符串\S\+,然后将新行字符转换为逗号。这对于大文件来说应该非常快。


3

试试这个:

sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*"\1,"'
sedClearLastComma='s"\(.*\),$"\1"'
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"

好消息是删除换行符"\n"很容易!

另外一个使用sed将多行合并成单行的好方法是:|sed ':a;N;$!ba;s/\n/ /g',参考自这里


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