タブ区切りファイルの単一列の重複項目に別の文字列を追加して一意にする方法

タブ区切りファイルの単一列の重複項目に別の文字列を追加して一意にする方法

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ループを使用してこれをどのように実行できますか?sedfor

ベストアンサー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 たとえば、ループ操作をより効率的な方法で独自に実行できるためです。

おすすめ記事