
次の構造のファイルがあります。
Locus7625186 GO0004866
Locus7625186 GO0010951
Locus7625186 GO0005615
Locus7625186 GO0016021
Locus7360093 GO0004712
Locus7360093 GO0007093
Locus1507198 GO0044212
Locus1507198 GO0045944
Locus1507198 GO0005634
Locus1507198 GO0036464
Locus1507198 GO0046982
これを次のように変換する必要があります。
Locus7625186 GO0004866 GO0010951 GO0005615 GO0016021
Locus7360093 GO0004712 GO0007093
Locus1507198 GO0044212 GO0045944 GO0005634 GO0036464 GO0046982
GOxxxxxxx
同じ最初の列を共有する一致の数は異なります。
答え1
そしてGNUデータ統合
$ datamash -W groupby 1 collapse 2 < file | sed 's/,/ /g'
Locus7625186 GO0004866 GO0010951 GO0005615 GO0016021
Locus7360093 GO0004712 GO0007093
Locus1507198 GO0044212 GO0045944 GO0005634 GO0036464 GO0046982
(デフォルトのカンマ区切り文字が気に入らない場合は、sedからパイプを省略できます)。
答え2
GNU sed
ストリームエディタを使用してこの問題を解決できます。
sed -Ee '
:a
$!N
s/^((\S+)\s.*)\n\2(\s.*)/\1\3/
ta
P;D
' file
結果
Locus7625186 GO0004866 GO0010951 GO0005615 GO0016021
Locus7360093 GO0004712 GO0007093
Locus1507198 GO0044212 GO0045944 GO0005634 GO0036464 GO0046982
これは次の方法で行うこともできますPOSIX sed
。
sed -e '
:a
$!N
s/^\(\([^[:space:]]\{1,\}\)[[:space:]].*\)\n\2\([[:space:]].*\)/\1\3/
ta
P;D
' file
答え3
sed
小さくてポータブルで奇妙な別のアプローチは次のとおりです。
sed 'N;/^\(.*\)\( .*\)\(\n\1\)/!P;s//\3\2/;D'
- この
N;P;D
方法を使用すると、パターンスペースに常に2行があるため、N
次の行を最初に追加します。 /^\(.*\) .*\n\1/
単語、空白、他の単語、改行、および繰り返される最初の単語で始まる行を一致させるため、バッファの2行は最初の(Locus
)単語を共有します。そうでない場合(!
)P
、最初の行は完成したものとして印刷され、後で次のように削除できます。D
- ただし、行が一致する場合は、最初の単語が同じ2行あり、改行と重複する単語を削除して置換を実行できます。だから私はアドレスパターンに2つのサブグループを追加したので、これを
P
繰り返すことなく空のパターンを使用して再利用します。 - これでトリックが出ます。パターンスペースに空の最初の行があり、その後に最初の単語とこれまでに持っていたすべての2番目の単語を含む2番目の行があるように
first second\nfirst
置き換えます。\nfirst second
次に、空D
の最初の行を削除し、これまでに収集された行を引き続き使用します。これを一致に含めると交換する必要がないため、\n
移植性はありません。\3
\n
答え4
awk '!a[$1]{b[++p]=$1; a[$1]=$2;next} {a[$1]=sprintf("%s%s%s", a[$1], OFS, $2)} END {for (i=1; i<=p; i++) print b[i], a[b[i]]}' file
この記事に基づいて最初のフィールド/要素に基づいて行をグループ化する方法