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

假设我有以下字符串:

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?

172492 次浏览
$ 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

You can use awk and sed:

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

或者如果你想用管子:

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

分析一下:

  • awk非常擅长处理分解成字段的数据
  • -vORS=,将“输出记录分隔符”设置为 ,,这正是您想要的
  • { print $2 } tells awk to print the second field for every record (line)
  • file.txt是您的文件名
  • sed只是去掉了后面的 ,并将其转换为换行(如果不需要换行,可以转换为 s/,$//)

With 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

您也可以通过两个 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

First sed call removes uninteresting data, and the second join all lines.

This should work too

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

这可能对你有用:

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

or

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

对于文件中的每一行,删除第一个字段和后面的空格,删除第二个字段后面的行的其余部分,并附加到 hold 空格。删除所有行,除了最后一行,在这里我们切换到保持空间,并且在开始时删除引入的换行之后,将所有换行转换为 ,

N.B. Could be written:

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

你也可以这样打印:

使用 打印

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

简洁明了:

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

试试这个:

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'给你获得。

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

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

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

你可以使用 grep:

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

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

用纯 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

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

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

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

一个班轮

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


+12.0,+15.5,+9.0,+13.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

试试这个简单的代码:

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

又一个 AWK 解决方案

快跑

awk '{printf "%s", $c; while(getline){printf "%s%s", sep, $c}}' c=2 sep=','

使用第2列形成以逗号分隔的列表。在标准输入中或作为文件名参数给出输入。