2017-06-27 4 views
-3

は、私は、ファイルがあります:複数の文字列をキーで折りたたむ方法は?例えば

key1 1212 
key2 1212 
key1 32332 
key2 3232 
key2 3232 

は私が取得したいのファイル:awkでは

key1 1212,32332 
key2 1212,3232,3232 
+0

これはbashで可能なはずですが、私はあなたの脳を破壊するのではなく、示唆している - あなたはbashのに言わせれば、より良いツールを使用する - それは、Linuxの - 間違いなくPythonを使用しています - それを使用して、タスクは簡単になります。 – Drako

+0

私の答えに関するコメントのためにawkとpythonタグが追加されました。 –

答えて

1

$ awk '{a[$1]=a[$1](a[$1]==""?"":",")$2}END{for(i in a)print i,a[i]}' file 
key1 1212,32332 
key2 1212,3232,3232 

はの説明:

awk '{          # use awk for this kind of stuff 
    a[$1]=a[$1] (a[$1]=="" ? "" : ",") $2 # hash on first col and append seconds 
} 
END {           # after everything is hashed 
    for(i in a)        # for each entry in hash a 
     print i,a[i]       # output key and data 
}' file          # oh yeah the file 

編集: awkにバッファリングを行わせる代わりに(すなわち、ハッシュをaに)、sortを使用してファイルをソートし、そのキーとすべてのデータをカンマ区切りで出力することができます。ここでも後半のためにawkを使用して:

$ sort file | awk '$1!=p{printf "%s%s",(NR>1?ORS:""),$1}{printf "%s%s", ($1==p?",":OFS),$2;p=$1}END{print ""}' 
key1 1212,32332 
key2 1212,3232,3232 

ここsortしても、派手なパラメータを与えられていないが、現実の世界では、いくつかは、要求される可能性があります。 awkの部分は次のように説明し

sort file | \       # sort the file 
awk '         # before feeding to awk 
$1!=p {        # if key is different from previous key 
    printf "%s%s",(NR>1?ORS:""),$1  # newline and print the key 
} 
{ 
    printf "%s%s", ($1==p?",":OFS),$2 # print the data comma-separated 
    p=$1        # store key for comparing on the next round 
} 
END{ 
    print ""       # finish the last line nicely 
}' 
+0

答えはたぶん大丈夫だと思いますが、私は常にテキストファイルを解析するのを避けるためにbashを使っています。非効率です。あなたはその入力ファイルがどれくらい大きいか分からないので、本当に悪いことがあります:)とBdfyはあなたのSOの評判を考慮に入れています。もし私があなたの質問にタグのpythonを追加すれば、 bashよりも使用する方が良いです。 – Drako

+0

@Drako:「awk」は小さなファイルの場合は全く問題ないと言っています – sjsam

+1

@sjsam私は同意しますが、入力が500MB以上になると、あなたは本当にPythonソリューションに満足しています:)可能であれば、正しいツールを使用してください。成長する時期を決して知りません。 – Drako

0
awk '{a[$1]=(a[$1]!="")?a[$1]","$2:$2}END{for(i in a){print i "\t" a[i]}}' file 
key1 1212,32332 
key2 1212,3232,3232 

はそれを行う必要があります。

0

ファイル全体の結果をバッファリングしないようにするには(たとえば、ファイルが非常に大きい場合)、sortとPythonのitertools.groupbyを使用できます。このようにPythonスクリプトを作成します。

# group.py 

import itertools, sys 

for k, g in itertools.groupby(sys.stdin, lambda x: x.split()[0]): 
    print(k, ",".join([x.split()[1] for x in g])) 

を次に実行します。

perl -aE 'push @{$h{$F[0]}}, $F[1]; END {$"= ","; say "$_ @{$h{$_}}" for sort keys %h}' file 

sort file | python group.py 
key1 1212,32332 
key2 1212,3232,3232 

はそうでない場合は、このクイックPerlのワンライナーは、ハッシュの値を蓄積することで、同様に動作するはずです出力:

key1 1212,32332 
key2 1212,3232,3232 
0

それは純粋なSH/coreutilsのではないのですが、このタスクのためdatamashを使用することを検討してください:

sed -r -e 's/[[:space:]]+/ /g' < infile.txt | datamash -t ' ' -s groupby 1 collapse 2 
関連する問題