我想执行一些数据分析软件所谓的反连接:从一个列表中删除与另一个列表中的行匹配的行。这是一些玩具数据和预期输出:
$ 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
使用该实用程序执行此操作的一种方法join
是:
$ join -v 1 list1 list2
a
b
从联机帮助页:
-A文件号
:还打印文件 FILENUM 中不可配对的行,其中 FILENUM 为 1 或 2,对应于 FILE1 或 FILE2
-v文件号
: 喜欢-AFILENUM,但抑制连接的输出行
答案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)
最后,您可以通过将最后一行更改为.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/language/setbagmix#Operators_with_set_semantics
https://raku.org