BashでDejoinまたはReverse Joinを実行する方法

BashでDejoinまたはReverse Joinを実行する方法

一部のデータ分析ソフトウェアでは、アンチジョインと呼ばれるタスクを実行したいと思います。つまり、あるリストから別のリストの行に一致する行を削除することです。以下はいくつかのおもちゃのデータと予想される結果です。

$ echo -e "a\nb\nc\nd" > list1
$ echo -e "c\nd\ne\nf" > list2
$ antijoincommand list1 list2
a
b

答え1

join入力をソートする必要があるため使用しませんjoin。これは単純な作業に不必要な複雑さです。代わりに使用できますgrep

$ grep -vxFf list2 list1
a
b

またはawk:

$ awk 'NR==FNR{++a[$0]} !a[$0]' list2 list1
a
b

ファイルがすでにソートされている場合、代替は次のjoin -v 1とおりです。comm -23

$ comm -23 list1 list2 
a
b

答え2

ユーティリティを使用してこれを行う1つの方法は次のjoinとおりです。

$ join -v 1 list1 list2
a
b

マンページから:

-ㅏファイル番号

:FILENUMファイルでペアリングできない行も印刷します。ここで FILENUM は、FILE1 または FILE2 に対応する 1 または 2 です。

-Vファイル番号

:良い-ㅏFILENUM、しかし接続された出力ラインを抑制します。

答え3

使用幸せ(以前のPerl_6)

Rakuには、Set単一のファイルから読み取って次の行からコレクションを生成できるオブジェクトタイプがあります。

~$ raku -e 'my $a = Set.new: "list1".IO.lines; 
            my $b = Set.new: "list2".IO.lines; 
            say "list1 = ", $a;
            say "list2 = ", $b;'
list1 = Set(a b c d)
list2 = Set(c d e f)

ASCII中位またはUnicode中位を使用して、(-)非対称集合差を実行できます

~$ raku -e 'my $a = Set.new: "list1".IO.lines; 
            my $b = Set.new: "list2".IO.lines; 
            say $a (-) $b;'
Set(a b)
~$ raku -e 'my $a = Set.new: "list1".IO.lines; 
            my $b = Set.new: "list2".IO.lines; 
            say $b (-) $a;'
Set(e f)

OTOH、時にはやるべきことがあります。対称違いを設定すると、Rakuはあなたのニーズに適しています。 ASCII中位(^)またはUnicode中位を使用してください

~$ raku -e 'my $a = Set.new: "list1".IO.lines; 
            my $b = Set.new: "list2".IO.lines; 
            say $a (^) $b;'
Set(a b e f)

最後に、最後の行を...に変更して1行ずつ出力できます.keys.put for
決定的な対称以下は、Unicode中位演算子を使用して違いを設定する例です。

~$ raku -e 'my $a = Set.new: "list1".IO.lines;
            my $b = Set.new: "list2".IO.lines;
            .keys.put for $a ⊖ $b;'
f
e
a
b

https://docs.raku.org/type/Set
https://docs.raku.org/言語/setbagmix#Operators_with_set_semantics
https://raku.org

関連情報