uniq
是一种工具,可以一次过滤文件中的行,只显示唯一的行。 uniq
有一些支持来指定两行是否“等价”,但是选项是有限的。
我正在寻找uniq
上的工具/扩展,允许input一个正则expression式。 如果捕获的组对于两行是相同的,则这两行被认为是“等同的”。 每个等价类只返回“第一个匹配”。
例如 :
file.dat
:
foo!bar!baz !baz!quix !bar!foobar ID!baz!
使用grep -P '(!\w+!)' -o
,可以提取“独特的部分”:
!bar! !baz! !bar! !baz!
这意味着第一行被认为是与第三行相等,而第二行与第四行相等。 因此只有第一个和第二个被打印(第三个和第四个被忽略)。
然后uniq '(!\w+!)' < file.dat
应该返回:
foo!bar!baz !baz!quix
不使用uniq
但使用gnu-awk,你可以得到你想要的结果:
awk -v re='![[:alnum:]]+!' 'match($0, re, a) && !(a[0] in p) {p[a[0]]; print}' file foo!bar!baz !baz!quix
-v re=...
match
函数匹配每行的正则表达式,并返回[a]
匹配的文本 match
成功,我们将匹配的文本存储在关联数组p
并打印 regex
支持的uniq
功能 这是一个简单的Perl脚本,可以完成这个工作:
#!/usr/bin/env perl use strict; use warnings; my $re = qr($ARGV[0]); my %matches; while(<STDIN>) { next if $_ !~ $re; print if !$matches{$1}; $matches{$1} = 1; }
用法:
$ ./uniq.pl '(!\w+!)' < file.dat foo!bar!baz !baz!quix
在这里,我使用$1
来匹配第一个提取的组,但是您可以用$&
替换它以使用整个模式匹配。
这个脚本会过滤出不符合正则表达式的行,但是如果你需要不同的行为,你可以调整它。
你可以用grep
和sort
来做到这一点
DATAFILE=file.dat for match in $(grep -P '(!\w+!)' -o "$DATAFILE" | sort -u); do grep -m1 "$match" "$DATAFILE"; done
输出:
foo!bar!baz !baz!quix