将多行字符串转换为单个逗号分隔
Posted
技术标签:
【中文标题】将多行字符串转换为单个逗号分隔【英文标题】:Turning multi-line string into single comma-separated 【发布时间】:2012-02-01 14:46:58 【问题描述】:假设我有以下字符串:
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 中?
【问题讨论】:
让我们退后一步,考虑一下这个线程是对 bash 作为编程语言的明显控诉。考虑 Scala 的listOfStuff mkString ", "
或 Haskell 的 intercalate ", " listOfString
相关:Convert text file into a comma delimited string
【参考方案1】:
另一个 AWK 解决方案
运行
awk 'printf "%s", $c; while(getline)printf "%s%s", sep, $c' c=2 sep=','
使用第 2 列形成以逗号分隔的列表。像往常一样在标准输入中或作为文件名参数提供输入。
【讨论】:
【参考方案2】:试试这个简单的代码:
awk 'printf("%s,",$2)' File1
【讨论】:
它添加了一个额外的逗号【参考方案3】:这可能对你有用:
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
对于文件中的每一行;砍掉第一个字段和后面的空格,砍掉第二个字段后面的行的其余部分并附加到保留空间。删除除我们交换到保留空间的最后一行之外的所有行,并在删除开头引入的换行符后,将所有换行符转换为,
's。
注意可以写成:
sed 's/\S\+\s\+//;s/\s.*//;1h;1!H;$!d;x;s/\n/,/g' file
【讨论】:
【参考方案4】:干净简单:
awk 'print $2' file.txt | paste -s -d, -
【讨论】:
这是最好的答案,显然是正确的方法 如何用单/双引号引用每个值? @Hussaincat thing | awk -F',' ' print "'\''" $7 "'\' '" ' | paste -s -d ','
如何使用,'
作为分隔符?
如果字符串中有任何 CRLF,请记住处理 Windows 换行符(例如使用dos2unix
)。【参考方案5】:
好吧,最难的部分可能是选择第二个“列”,因为我不知道有一种简单的方法可以将多个空格视为一个空格。其余的很容易。使用 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
【讨论】:
【参考方案6】:awk 一个班轮
$ awk 'printf (NR>1?",":"") $2' file
+12.0,+15.5,+9.0,+13.5
【讨论】:
格式说明符"%s",
应该在printf
之后添加以使其更健壮,即使其适用于所有类型的行,例如“foo %s”。【参考方案7】:
没有看到这个简单的 awk 解决方案
awk 'bb=b","b=b$2ENDprint b' infile
【讨论】:
【参考方案8】:cat data.txt | xargs | sed -e 's/ /, /g'
【讨论】:
我也喜欢这样的解决方案,但这里是否需要 -e arg,因为只有第一个命令用于 sed?我相信cat data.txt | xargs | sed 's/ /, /g'
会一样工作。例如,echo -e "foo\nbar\nbazz" | xargs | sed 's/ /, /g'
输出 foo, bar, bazz。【参考方案9】:
用纯 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
【讨论】:
您也可以使用read -r -a cols
,然后将"$cols[1]
添加到列表a
。【参考方案10】:
你可以使用grep
:
grep -o "+\S\+" in.txt | tr '\n' ','
查找以+
开头的字符串,后跟任何字符串\S\+
,然后将换行符转换为逗号。对于大文件,这应该很快。
【讨论】:
【参考方案11】:另一个 Perl 解决方案,类似于 Dan Fego 的 awk:
perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'
-a
告诉 perl 将输入行拆分为 @F 数组,该数组从 0 开始索引。
【讨论】:
【参考方案12】:试试这个:
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'
got from here。
【讨论】:
那个编辑很棒 - +1!【参考方案13】:你也可以这样打印:
只是 awk:使用 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
【讨论】:
【参考方案14】:这应该也可以
awk 'print $2' file | sed ':a;N;s/\n/,/;ba'
【讨论】:
【参考方案15】:$ 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...
?【参考方案16】:
你也可以通过两个 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 调用删除不感兴趣的数据,第二个加入所有行。
【讨论】:
【参考方案17】:使用 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
【讨论】:
【参考方案18】:您可以使用awk
和sed
:
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/,$//
)
【讨论】:
awk: 无效的 -v 选项 :( 在 -v 和 ORS= 之间添加一个空格,(对我来说,在 osx 上) 如何执行相同的命令来分离管道?awk -v ORS=| ' print $1 ' DCMC.rtf | sed 's/,$/\n/'
遇到错误
奇怪的是,当我尝试这样做时,输出为空。
我认为管道版本应该是 print $1
否则我在输出中只会得到逗号以上是关于将多行字符串转换为单个逗号分隔的主要内容,如果未能解决你的问题,请参考以下文章
如何将包含逗号分隔的 json 值的单个字符串转换为单个 json 对象?