将多行字符串转换为单逗号分隔


95

假设我有以下字符串:

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

b?


让我们退后一会,将此线程视为bash作为编程语言的明显指示。考虑Scala的listOfStuff mkString ", ",或者Haskell的intercalate ", " listOfString
FP自由

Answers:


92

您可以使用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 2015年

6
在-v和ORS =之间添加一个空格,(对我来说,在osx上)
Graham P Heath 2015年

如何执行相同的命令来分离管道?awk -v ORS=| '{ print $1 }' DCMC.rtf | sed 's/,$/\n/'遇到错误
Yogesh

2
奇怪的是,当我尝试执行此操作时,输出为空。
eternaltyro '19

1
我认为管道版本,它应该{print $1}否则我只得到逗号输出
普热Czechowski

162

干净简单:

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

3
这是最好的答案,而且显然是正确的方法
forresthopkinsa

如何用单引号/双引号引用每个值?
侯赛因

1
@侯赛因cat thing | awk -F',' '{ print "'\''" $7 "'\' '" }' | paste -s -d ','
starbeamrainbowlabs

如何,'用作分隔符?
Kasun Siyambalapitiya

如果字符串中有任何CRLF,请记住要处理Windows换行符(例如,使用dos2unix)。
Bowi


10
$ 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,2012年



8

这可能对您有用:

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

对于文件中的每一行;切掉第一个字段及其后的空格,切掉第二个字段之后的行的其余部分,并追加到保留空间。删除除最后一个交换到保留空间的行以外的所有行,并在开始处删除引入的换行符后,将所有换行符转换为,

NB可以写成:

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

4

您可以使用grep

grep -o "+\S\+" in.txt | tr '\n' ','

会找到以开头的字符串+,后跟任意字符串\S\+,然后将换行符转换为逗号。对于大文件,这应该很快。


4

试试这个简单的代码:

awk '{printf("%s,",$2)}' File1

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'这里得到。


该编辑很棒-+1!
JoeG 2013年

2

用纯Bash编写的解决方案:

#!/bin/bash

sometext="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)"

a=()
while read -r a1 a2 a3; do
    # we can add some code here to check valid values or modify them
    a+=("${a2}")
done <<< "${sometext}"
# between parenthesis to modify IFS for the current statement only
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}")

结果:+ 12.0,+ 15.5,+ 9.0,+ 13.5


2

没有用awk看到这个简单的解决方案

awk 'b{b=b","}{b=b$2}END{print b}' infile

0

使用perl:

fg@erwin ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF
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)
EOF

+12.0,+15.5,+9.0,+13.5

0

您还可以通过两个sed调用来做到这一点:

$ cat file.txt 
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)
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta'
+12.0,+15.5,+9.0,+13.5

sed的第一个调用将删除无用的数据,第二个连接所有行。


0

您也可以这样打印:

刚好:使用printf

bash-3.2$ cat sample.log
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)

bash-3.2$ awk ' { if($2 != "") { if(NR==1) { printf $2 } else { printf "," $2 } } }' sample.log
+12.0,+15.5,+9.0,+13.5

0

另一个Perl解决方案,类似于Dan Fego的awk:

perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'

-a 告诉perl将输入行拆分为@F数组,该数组从0开始索引。


0

好吧,最困难的部分可能是选择第二个“列”,因为我不知道将多个空间视为一个的简单方法。剩下的事情很简单。使用bash替代。

# cat bla.txt
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)

# cat bla.sh
OLDIFS=$IFS
IFS=$'\n'
for i in $(cat bla.txt); do
  i=$(echo "$i" | awk '{print $2}')
  u="${u:+$u, }$i"
done
IFS=$OLDIFS
echo "$u"

# bash ./bla.sh
+12.0, +15.5, +9.0, +13.5
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.