使用ack或awk或者比grep更好的方式从另一个文件中获取模式?

Roc*_*ock 5 regex perl awk grep ack

有没有办法从另一个文件中获取模式(模式列表)ack作为-f选项grep?我看到有一个-f选项,ack但它与-fin 有所不同grep.

也许一个例子会给你一个更好的主意.假设我有file1:

file1:
a
c
e
Run Code Online (Sandbox Code Playgroud)

和file2:

file2:
a  1
b  2
c  3
d  4
e  5
Run Code Online (Sandbox Code Playgroud)

我想从file2获取file1中的所有模式,以便:

a  1
c  3
e  5
Run Code Online (Sandbox Code Playgroud)

可以ack这样吗?否则,是否有更好的方法来处理作业(比如awk使用哈希),因为我在这两个文件中都有数百万条记录,真的需要一种有效的方法来完成?谢谢!

Dav*_*idO 8

这是一个Perl单行程序,它使用散列来保存来自file1的有用键集,用于在file2行上每次迭代进行O(1)(分摊时间)查找.因此它将在O(m + n)时间内运行,其中m是键集中的行数,n是您正在测试的文件中的行数.

perl -ne'BEGIN{open K,shift@ARGV;chomp(@a=<K>);@hash{@a}=()}m/^(\p{alpha}+)\s/&&exists$hash{$1}&&print' tkeys file2

密钥集将保存在内存中,而file2则逐行对密钥进行测试.

使用Perl的-a命令行选项也是如此:

perl -ane'BEGIN{open G,shift@ARGV;chomp(@a=<G>);@h{@a}=();}exists$h{$F[0]}&&print' tkeys file2

第二个版本可能在眼睛上更容易一些.;)

你必须要记住的一件事是,你更有可能是IO绑定而不是处理器绑定.因此,目标应该是尽量减少IO的使用.当整个查找键集保存在提供O(1)分摊查找的散列中时.此解决方案可能优于其他解决方案的优点是,某些(较慢)解决方案必须为每行file2一次运行密钥文件(file1).那种解决方案将是O(m*n),其中m是密钥文件的大小,n是file2的大小.另一方面,该散列方法提供O(m + n)时间.这是一个巨大的差异.它通过消除按键的线性搜索而获益,并且通过IO只读一次键可以获得更多好处.


gho*_*oti 6

好吧,如果我们从评论转到答案...... ;-)

这是一个awk单线程,与DavidO的perl单线程相同,但是在awk中.Awk比Perl更小,可能更精简.但是有一些不同的awk实现.我不知道你的表现会比其他人更好,还是比perl更好.你需要进行基准测试.

awk 'NR==FNR{a[$0]=1;next} {n=0;for(i in a){if($0~i){n=1}}} n' file1 file2
Run Code Online (Sandbox Code Playgroud)

(应该)这是做什么的?

awk脚本的第一部分仅匹配file1中的行(其中当前文件中的记录号等于记录总数),并填充数组.第二部分(在后续文件上运行)逐步遍历数组中的每个项目,并查看它是否可以用作匹配当前输入行的正则表达式.

第二个代码块以"n"开头,在前一个块中设置为0或1.在awk中,"1"的计算结果为true,并且缺少花括号块被认为是等效的{print},因此如果前一个块找到匹配项,则该块将打印当前行.

如果file1包含字符串而不是正则表达式,那么您可以通过替换第一个比较来更改它以使其运行更快if(index($0,i))....

谨慎使用.你的旅费可能会改变.在可能含有坚果的设施中创建.