gpt4 book ai didi

bash - 检查文件中是否存在所有多个字符串或正则表达式

转载 作者:行者123 更新时间:2023-11-29 08:45:35 27 4
gpt4 key购买 nike

我想检查我的所有 字符串是否存在于文本文件中。它们可以存在于同一条线上,也可以存在于不同的线上。部分匹配应该没问题。像这样:

...
string1
...
string2
...
string3
...
string1 string2
...
string1 string2 string3
...
string3 string1 string2
...
string2 string3
... and so on

在上面的例子中,我们可以用正则表达式代替字符串。

例如下面的code检查文件中是否存在任何我的字符串:

if grep -EFq "string1|string2|string3" file; then
# there is at least one match
fi

如何检查所有是否存在?由于我们只对所有匹配项存在感兴趣,因此我们应该在所有字符串都匹配后立即停止读取文件。

是否可以在不必多次调用 grep 的情况下(当输入文件很大或者我们有大量字符串要匹配时不会缩放)或使用工具来做到这一点像 awk 还是 python

此外,是否有可以轻松扩展为正则表达式的字符串解决方案?

最佳答案

Awk 是发明 grep、shell 等的人发明的用于执行此类一般文本操作工作的工具,因此不确定您为什么要尝试避免使用它。

如果您想要的是简洁,这里是 GNU awk 单行代码,可以满足您的要求:

awk 'NR==FNR{a[$0];next} {for(s in a) if(!index($0,s)) exit 1}' strings RS='^$' file

还有一些其他信息和选项:

假设你真的在寻找字符串,它会是:

awk -v strings='string1 string2 string3' '
BEGIN {
numStrings = split(strings,tmp)
for (i in tmp) strs[tmp[i]]
}
numStrings == 0 { exit }
{
for (str in strs) {
if ( index($0,str) ) {
delete strs[str]
numStrings--
}
}
}
END { exit (numStrings ? 1 : 0) }
' file

一旦所有字符串都匹配,上述将停止读取文件。

如果您正在寻找正则表达式而不是字符串,那么使用 GNU awk 进行多字符 RS 并在 END 部分保留 $0,您可以这样做:

awk -v RS='^$' 'END{exit !(/regexp1/ && /regexp2/ && /regexp3/)}' file

实际上,即使是字符串你也可以这样做:

awk -v RS='^$' 'END{exit !(index($0,"string1") && index($0,"string2") && index($0,"string3"))}' file

上述 2 个 GNU awk 解决方案的主要问题是,就像@anubhava 的 GNU grep -P 解决方案一样,整个文件必须一次读入内存,而对于上面的第一个 awk 脚本,它将在任何 UNIX 机器上任何 shell 中的任何 awk,一次只存储一行输入。

我看到你在你的问题下添加了一条评论说你可以有几千个“模式”。假设您的意思是“字符串”,那么您可以从文件中读取它们,而不是将它们作为参数传递给脚本,例如使用 GNU awk 进行多字符 RS 和一个每行一个搜索字符串的文件:

awk '
NR==FNR { strings[$0]; next }
{
for (string in strings)
if ( !index($0,string) )
exit 1
}
' file_of_strings RS='^$' file_to_be_searched

对于正则表达式,它是:

awk '
NR==FNR { regexps[$0]; next }
{
for (regexp in regexps)
if ( $0 !~ regexp )
exit 1
}
' file_of_regexps RS='^$' file_to_be_searched

如果您没有 GNU awk 并且您的输入文件不包含 NUL 字符,那么您可以通过使用 RS='\0' 而不是 RS 来获得与上面相同的效果='^$' 或在读取变量时一次追加一行,然后在 END 部分处理该变量。

如果您的 file_to_be_searched 太大而无法放入内存,那么对于字符串来说就是这样:

awk '
NR==FNR { strings[$0]; numStrings=NR; next }
numStrings == 0 { exit }
{
for (string in strings) {
if ( index($0,string) ) {
delete strings[string]
numStrings--
}
}
}
END { exit (numStrings ? 1 : 0) }
' file_of_strings file_to_be_searched

和正则表达式的等价物:

awk '
NR==FNR { regexps[$0]; numRegexps=NR; next }
numRegexps == 0 { exit }
{
for (regexp in regexps) {
if ( $0 ~ regexp ) {
delete regexps[regexp]
numRegexps--
}
}
}
END { exit (numRegexps ? 1 : 0) }
' file_of_regexps file_to_be_searched

关于bash - 检查文件中是否存在所有多个字符串或正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49762772/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com