4列のタブで区切られたファイルがあり、最後の列に重複することがあります。以下は文書から抜粋したものです。
chr7 116038644 116039744 GeneA
chr7 116030947 116032047 GeneA
chr7 115846040 115847140 GeneA
chr7 115824610 115825710 GeneA
chr7 115801509 115802609 GeneA
chr7 115994986 115996086 GeneA
chrX 143933024 143934124 GeneB
chrX 143933119 143934219 GeneB
chrY 143933129 143933229 GeneC
列の各重複値セットに対して、次のように変換したいと思います(列の重複しない値に実際に触れることなく)。
chr7 116038644 116039744 GeneA-1
chr7 116030947 116032047 GeneA-2
chr7 115846040 115847140 GeneA-3
chr7 115824610 115825710 GeneA-4
chr7 115801509 115802609 GeneA-5
chr7 115994986 115996086 GeneA-6
chrX 143933024 143934124 GeneB-1
chrX 143933119 143934219 GeneB-2
chrY 143933129 143933229 GeneC
または、Bashawk
ループを使用してこれをどのように実行できますか?sed
for
ベストアンサー1
この試み
awk -F'\t' -v OFS='\t' '{$4=$4 "-" (++count[$4])}1' file.tsv
これは、4番目のフィールド値の各発生をカウンタの配列count
(4番目のフィールドの値が「インデックス」として使用されます)に格納し、そのカウンタの事前に増加した値を4番目のフィールドとダッシュに追加します。
上記の「簡単な」例には1つの欠点があります。ファイルに一度だけ表示される列4の値に明確性番号を追加することもできます。これを抑制するには、次のようなデュアル転送アプローチを使用できます(読みやすくするためにコマンドを2行に分割\
)。
awk -F'\t' -v OFS='\t' 'NR==FNR{f[$4]++}\
NR>FNR{if (f[$4]>1) {$4=$4 "-" (++count[$4])}; print}' file.tsv file.tsv
処理するファイルが記録されています。二重パラメータとして使用されるため、2回読み取られます。
- 最初の読み取り(グローバル
FNR
行カウンターと同じファイル別のNR
行カウンターで表されます)では、列4の各固有値がファイルに表示される頻度を計算し、それを配列に保存しますf
。 - 2番目にファイルを読み取るときは、「簡単な」方法などの実際のテキスト処理を実行し、発生カウンタを列4に追加します。ただし、最初のパスで見つかった総発生回数が1より大きい場合にのみ該当します。
このアプローチは、ファイル全体のバッファリングを防ぎ、ファイルが非常に大きい場合に利点となります。もちろん、ファイルを2回読み取るため、処理時間が長くなります。
通常、テキスト処理にシェルループを使用する必要はほとんどありません。awk
たとえば、ループ操作をより効率的な方法で独自に実行できるためです。