列値に基づいて一意の行を取得する方法

列値に基づいて一意の行を取得する方法

次のように入力します。

A 13
A 12
B 17
C 33
D 344
C 24
A 5
C 99

最初の列だけの行を取得したいと思います。

B 17
D 344

1つの解決策でawkあれば良いですが、他の解決策も許可されています。

答え1

順序を混ぜるのが大丈夫なら

sort <file> | uniq -uw 1

詳細については、リソースを参照してくださいman uniq。重要な部分は次のとおりです。

   -u, --unique
          only print unique lines
   -w, --check-chars=N
          compare no more than N characters in lines

答え2

そしてawk

awk 'NR==FNR { a[$1]++ } NR!=FNR && a[$1]==1' file file

(ファイル名は2回渡されます。)

編集する:ファイルがソースの場合は、stdin一時コピーが必要です。このような:

tmp="$( mktemp -t "${0##*/}"_"$$"_.XXXXXXXX )" && \
    trap 'rm -f "$tmp"' 0 HUP INT QUIT TERM || exit 1
... | tee "$tmp" | awk '...' - "$tmp"

答え3

やる意思があればアッ

awk '
    $1 in ARR{
        ARR[$1] = RS;
        next;
    }
    {
        ARR[$1] = $0;
    }
    END{
        for(i in ARR)
            if(ARR[i] != RS)
                print ARR[i];
    }
    ' file

スクリプトは、最初のフィールドをインデックスとして、行全体を値として使用して、行をARR配列に入れます。配列にすでに同じインデックスがある場合は、値を「\ n」(改行)記号に変更します。ファイルの末尾に、値が«\ n»と等しくない配列要素を印刷します。
awkのRS変数はnewline基本的に同じです。

それともこれを行うことができます。sed

sort file |
sed '
    :a;
    $!N;
    s/\(\S\+\s\).*\n\1.*/\1\a/;
    ta;
    /\a/P;
    D;
    '

答え4

perl -lane '
   exists $h{$F[0]} and undef $h{$F[0]},next;

   ( $h{$F[0]}, $h[@h] ) = ( $_, $F[0] );

   END{ print $h{$_} for grep { defined $h{$_} } @h }
' yourfile

コードが行うことは、最初のフィールドが以前に見つかったことを確認することです。その後、その名前のキーがハッシュに存在するため、undefとにかく配列を構築する必要がないため、その特定のキーの値を計算し続けます。結局廃棄されます。代わりに、私たちは小さな記憶刻印を通して同じ情報を渡します。

最初のフィールドが最初に表示されたら、%hハッシュを現在の行で埋め、同時にそのキーで@h配列を追加します。キーが見つかった順序を維持するために、この手順を実行します。注文が気に入らない場合は、この手順を完全にキャンセルできます。

最後に、すべての入力がダイジェストされると、最後のENDブロックで配列要素を繰り返して、定義された値を@hハッシュする要素のみを見つけます。値が複数回表示されることを忘れないで%hください。undef

関連情報