次のようにスペースで区切られたテキストファイルがあります。
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3,id4 text4c text5c
text1d text2d id5,id6,id7 text4d,text4di text5d
ファイルの長さは約150万短くなります。
一部の行には、例の行3など、カンマで区切られた2つのIDがあります。id3
これにより、ファイルを他のファイル(IDまたは可能性がある)に関連付けようとしたときに問題が発生しますid4
。
列3にコンマがあるすべてのインスタンスを見つけ、両方の内容を別々の行に分けたいと思います。たとえば、上記のファイルは次のようになります。
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d
一部の行には、カンマで区切られた3つ以上のIDが含まれています。コンマは別の列に表示されることがありますが、そのままにしておく必要があります。順序は重要ではありません。たとえば、id3 または id4 がファイルから最初に出るかどうかです。
私はピアリングの経験が非常に少なく、awk
これがsed
その仕事に最適なツールだと思います。
誰もが正しい方向に私を指すことができますか?
答え1
$ awk 'split($3,f,/,/)>1{for (i=1; i in f; i++) {$3=f[i]; print} next } 1' file
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d
上記は、$ 3に記載されているIDの順序を維持します。不要な場合にfor (i in f)
置き換えることができますfor (i=1; i in f; i++)
。
Split() が 1 より大きい値を返す場合、無条件割り当てを実行するよりも $3 を割り当てるループブロックを実行する方が効率的です。なぜなら、フィールドへの各割り当ては、awkが現在のレコードを書き換えることを強制し、すべてのFSをOFSに置き換えるからです。 。
答え2
線が分割される順序は重要ではないため、次のように分割できますawk
。
$ awk '{ split($3,a,","); for (i in a) { $3 = a[i]; print } }' file
text1a text2a id1 text4a text5a
text1b text2b id2 text4b text5b
text1c text2c id3 text4c text5c
text1c text2c id4 text4c text5c
text1d text2d id5 text4d,text4di text5d
text1d text2d id6 text4d,text4di text5d
text1d text2d id7 text4d,text4di text5d
各行に対して、3番目のフィールドをコンマに配置して配列を作成しますa
。フィールドにカンマがない場合、配列には単一の要素のみを含めることができます。
その後、コードは配列のインデックスを繰り返しa
(配列の実装方法に応じて任意の順序で実行できますawk
)、3番目のフィールドを配列の現在の要素に設定して変更し、a
全体を印刷します。 (修正されることがあります)記録。
答え3
別のアプローチは次のとおりです。
cat fun.awk
$3~/^id[0-9]+,/ {
split($3, store, ",");
for (i = 1; i in store; i++)
print $1, $2, store[i], $4, $5
next
}
{ print $0 }
3番目の列にカンマ($3~/^id[0-9]+,/
)が含まれている場合は、それらを分割し、各列に1行を印刷して次のループに移動します。それ以外の場合は、行全体を印刷します($0
)。