我有一个文件(模式文件),我想通过 提供给 grep -f
,并且我想在另一个文件(搜索文件)中查找匹配项,其中有一个字符串以。。开始给定的模式。例如:
模式文件
1234
qwerty
chicken
搜索文件
12345
543212345
qwerty
1fwf32sgww
chicken fingers
鉴于上述文件,grep 应返回以下行
12345
qwerty
chicken fingers
我该怎么做?
答案1
您可以^
在所有行前面加上PATERN_FILE
要传递到的grep -f
:
paste -d '^' /dev/null PATTERN_FILE | grep -f - SEARCH_FILE
或者sed 's/^/^/' PATTERN_FILE
代替paste
.
现在,如果中的行PATTERN_FILE
是固定字符串而不是基本正则表达式,那么您还需要转义所有正则表达式运算符:
sed 's/[][$^*\\.]/\\&/g; s/^/^/' PATTERN_FILE | grep -f - SEARCH_FILE
答案2
替代方案:您可以使用 awk 而不是 grep 来进行匹配:
awk 'NR==FNR{a[$0];next} {for(t in a) if(substr($0,1,length(t))==t){print;next}}' needles haystack
这避免了 grep 中正则表达式引擎的开销,但有 awk 的解释开销;我不确定哪个效果更好。
答案3
使用乐(以前称为 Perl_6)
~$ raku -ne 'BEGIN my @a = "/path/to/pattern_file.txt".IO.lines; \
.put if .starts-with( any @a );' search_file.txt
#OR
~$ raku -ne 'BEGIN my @a = "/path/to/pattern_file.txt".IO.lines; \
.put if .starts-with( [|] @a );' search_file.txt
以上是用 Raku(Perl 编程语言家族的成员)编写的答案。假设这里的pattern_file.txt
是固定字符串而不是基本的正则表达式,Raku 有字符串匹配函数,如starts-with
和ends-with
。乐库也有路口像any
、all
、one
、none
一样可以简化这个匹配问题。
上面-ne
使用了非自动打印命令行标志,它逐行读取输入文件。在BEGIN
块中将其pattern_file.txt
读入@a
数组。在代码正文中,如果输入行以(第一个答案)的元素put
开头,则输入行将退出。或者(第二个答案),Raku 的归约元运算符符号用于在概念上插入一个any
@a
[ ]
|
或者的元素之间的运算符@a
。第一个和第二个答案给出相同的结果。
输入示例:
pattern_file.txt
1234
qwerty
chicken
search_file.txt
12345
543212345
qwerty
1fwf32sgww
chicken fingers
示例输出:
12345
qwerty
chicken fingers
注意:人们很容易认为one
连接点(或等效的[^]
归约元运算符)将完成相同的任务,但这仅在每行都是patterns_file.txt
唯一的情况下才成立!
https://docs.raku.org/routine/starts-with
https://docs.raku.org/type/Junction
https://docs.raku.org/language/operators#Reduction_metaoperators
https://raku.org
答案4
执行此操作的一个选项是首先修改模式文件,使用如下所示的命令将字符添加^
到每行的开头。这将指示 grep 通过正则表达式仅匹配行的开头。
awk '{print "^" $0}' PATTERN_FILE
然而,这会修改模式文件,我更喜欢一个不会改变原始列表的解决方案