タブ区切りのテキストファイルから重複した値を削除する方法

タブ区切りのテキストファイルから重複した値を削除する方法

以下のようにタブ区切りの列テキストがあります。

A      B1      B1     C1
B      B2      D2 
C      C12     C13    C13
D      D3      D5      D9
G      F2      F2   

上記の表を次のように変換するにはどうすればよいですか?

A      B1     C1
B      B2     D2 
C      C12    C13
D      D3     D5     D9
G      F2   

実際のデータファイルを抽出しました。タブ区切りファイルです。あなた(Stéphane Chazelas?)が投稿したコマンドラインを試してみましたが、うまくいきますが、最後の列の重複エントリを削除できませんでした。

A  CD274    PDCD1LG2  CD276   PDCD1LG2  CD274
B  NEK2     NEK6      NEK10   NEK10     NEKL-4
C  TNFAIP3  OTUD7B    OTUD7B  TNFAIP3   TNFAIP3
D  DUSP16   DUSP4     DUSP8   VHP-1     DUSP8
E  AGO2     AGO2      AGO2    AGO2      AGO2

出力は次のようにする必要があります

A  CD274    CD276   PDCD1LG2
B  NEK2     NEK6    NEK10     NEKL-4
C  TNFAIP3  OTUD7B
D  DUSP16   DUSP4   DUSP8     VHP-1
E  AGO2

答え1

最初のサンプルデータセット:

$ awk -vOFS='\t' '{ r=""; delete t; for (i=1;i<=NF;++i) { if (!t[$i]++) { r = r ? r OFS $i : $i } } print r }' file
A       B1      C1
B       B2      D2
C       C12     C13
D       D3      D5      D9
G       F2

2番目のサンプルデータセット(同じawkスクリプト):

$ awk -vOFS='\t' '{ r=""; delete t; for (i=1;i<=NF;++i) { if (!t[$i]++) { r = r ? r OFS $i : $i } } print r }' file
A       CD274   PDCD1LG2        CD276
B       NEK2    NEK6    NEK10   NEKL-4
C       TNFAIP3 OTUD7B
D       DUSP16  DUSP4   DUSP8   VHP-1
E       AGO2

スクリプトは入力ファイルを1行ずつ読み取り、各行ごとfileに各フィールドを繰り返して出力行を作成しますr。フィールドの値が出力行に追加されている場合(t使用されたフィールド値のルックアップテーブルによって決まります)の場合、そのフィールドは無視され、それ以外の場合は追加されます。

入力行のすべてのフィールドが処理されると、構成された行が出力されます。

-vOFS='\t'出力フィールド区切り文字はコマンドラインのタブに設定されます。


公開スクリプトawk

{
    r = ""
    delete t

    for (i = 1; i <= NF; ++i) {
        if (!t[$i]++) {
            r = r ? r OFS $i : $i
        }
    }

    print r
}

答え2

sed/tr、uniq、貼り付け

while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test

またはPOSIX互換:

while read -r l; do echo "$l" | tr '\t' '\n' | uniq | paste -s -; done < test

ファイルの場合は、すべての文字を1行ずつ改行文字に置き換え、重複項目を削除し、改行文字を再文字に置き換えるために実行しますtestTabuniqTab

$ cat test
A       B1      B1      C1
B       B2      D2
C       C12     C13     C13
D       D3      D5      D9
G       F2      F2

$ while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test
A       B1      C1
B       B2      D2
C       C12     C13
D       D3      D5      D9
G       F2

気づく:このソリューションはいいえ複数行にわたる重複操作に使用されますC1

A       B1      B1      C1
C1      B       B2      D2

答え3

たぶん、次のようなものがあります。

gawk -vRS='\\s*\\S*' -vORS= '{$0=RT};$1!=prev;{prev=$1}'

RS=pattern...トリックを使用すると、{$0=RT}パターンに一致する部分として定義されたレコードを処理できます。

したがって、ここでは入力を<whitespace><non-whitespace> $0レコードに切り捨て(最初と唯一のフィールド)を<non-whitespace>入力します。以前の記録と同じでない記録を$1印刷しています。$1

次のように入力すると:

A      B1      B1     C1
B      B2      D2 
C      C12     C13    C13
D      D3      D5      D9
G      F2      F2

記録は次のとおりです

[A][ B1] [ B1] [ C1][
雨][ B2][ D2][
C][ C12][ C13] [ C13] [
D] [D3] [D5] [D9] [
G][ F2] [ F2] [
]

しかし、2番目の例では機能しません。一部の改行文字が削除されることがあります。

答え4

そしてperl

各行には固有の単語があります。

perl -MList::Util=uniq -lape '$_ = join "\t", uniq @F'

世界で唯一の言葉:

perl -lape '$_ = join "\t", grep {!$count{$_}++} @F'

または、2行目から始まる各単語行を検討してください。

perl -lape '$_ = join "\t", shift(@F), grep {!$count{$_}++} @F'

関連情報