web-dev-qa-db-ja.com

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

次の入力:

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

列1が一意である行のみを取得したい:

B 17
D 344

awkを使用した解決策はいいでしょうが、それ以外のものも受け入れられます。

4
Michael

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"
5
Satō Katsura

注文をスクランブルしてもかまわない場合は、

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
6
Sparhawk

ご希望の場合awk

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

スクリプトは、1番目のフィールドをインデックスとして、1行を値として、配列ARRに行を入れました。配列に既に同じインデックスがある場合、値を"\ n"(改行)記号に変更します。ファイルが終了した後、値が"\ n"に等しくない配列の要素を出力します
デフォルトでは、awkのRS変数はnewlineと等しいことに注意してください。

またはsedで実行できます

sort file |
sed '
    :a;
    $!N;
    s/\(\S\+\s\).*\n\1.*/\1\a/;
    ta;
    /\a/P;
    D;
    '
5
Costas
$ cut -d' ' -f1 <file | sort | uniq -d | sed 's/^/^/' | grep -v -f /dev/stdin file
B 17
D 344

これはまず、列を切り取り、並べ替えてuniq -dにフィードすることで、ファイルfileの最初の列にある重複したエントリを取り出します(重複のみを報告します)。

次に、結果の各行の前に^を付けて、行の先頭にアンカーされる正規表現を作成します。指定されたデータを含むsedコマンドの出力は

^A
^C

最後のgrepは、これらの正規表現を読み取り、それらのいずれにも一致しないすべての行をファイルから取り出します。 -f /dev/stdinを使用して、grepsedからパターンを読み取らせます。

結果は元のファイルと同じ順序になります。

3
Kusalananda
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の値は、2回以上見たことがあることを意味します。

2
user218374