複数行の文字列を単一のカンマ区切りに変換


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

バッシュで?


少し前に戻り、このスレッドをプログラミング言語としてのbashの明白な告発と考えてみましょう。Scala listOfStuff mkString ", "やHaskellのことを考えてみましょうintercalate ", " listOfString
FP Freely

回答:


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すべてのレコード(行)の2番目のフィールドを印刷するように指示します
  • file.txt あなたのファイル名です
  • sed末尾,を削除して改行に変換するだけです(改行が不要な場合は、実行できますs/,$//

1
awk:無効な-vオプション:(
Marsellus Wallace

6
-vとORS =の間にスペースを追加します(私にとっては、osx上)
Graham P Heath

パイプを分離するために同じコマンドを実行するにはどうすればよいですか?awk -v ORS=| '{ print $1 }' DCMC.rtf | sed 's/,$/\n/'エラーが発生します
Yogesh

2
奇妙なことに、これを実行しようとすると、出力が空になります。
eternaltyro

1
私はそれがあるべきパイプで連結されたバージョンのためだと思う{print $1}そうでない場合、私は出力にのみコンマを得ている
はPrzemyslaw Czechowski

162

クリーンでシンプル:

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

3
これがここでの最良の答えであり、明らかにこれを行う正しい方法です
forresthopkinsa '20

すべての値を一重/二重引用符で囲むにはどうすればよいですか?
フセイン

1
@フセインcat thing | awk -F',' '{ print "'\''" $7 "'\' '" }' | paste -s -d ','
starbeamrainbowlabs

,'区切り文字としてどのように使用しますか?
Kasun Siyambalapitiya

文字列にCRLFがある場合は、Windowsの改行(例:を使用dos2unix)を処理することを忘れないでください。
ボウイ


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



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

ファイルの各行。最初のフィールドとそれに続くスペースを切り取り、2番目のフィールドに続く行の残りを切り取り、ホールドスペースに追加します。ホールドスペースにスワップする最後の行を除くすべての行を削除し、最初に導入された改行を削除した後、すべての改行をに変換します,

注意:

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\+改行文字をコンマに変換します。大きなファイルの場合、これはかなり高速です。



3

これを試して:

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

良い点は、改行「\ n」文字を削除する簡単な部分です。

編集:sedを使用して行を1つの行に結合する別の優れた方法は、次のとおりですここ|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

次の2つの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呼び出しは興味のないデータを削除し、2番目はすべての行を結合します。


0

次のように印刷することもできます。

ただ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

0

Dan Fegoのawkに似た別のPerlソリューション:

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

-a 入力行を0から始まる@F配列に分割するようperlに指示します。


0

複数のスペースを1つとして扱う簡単な方法がわからないので、最も難しいのは、おそらく2番目の「列」を選択することです。残りは簡単です。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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.