我想在模式之间使用隐式AND进行多模式匹配,即等效于在序列中运行多个抓图:

grep pattern1 | grep pattern2 | ...


那么如何将其转换为类似我想使用单个grep,因为我是动态构建参数的,因此所有内容都必须放在一个字符串中。使用filter是系统功能,而不是grep,因此不是系统功能。


不要将此问题与以下内容混淆:

grep pattern1 & pattern2 & pattern3


这是一个或多模式匹配。

评论

相似:一次匹配文件中的所有模式

关于SO的类似问题:检查文件中是否存在多个字符串或正则表达式

如果要查找“包含foo的行和包含bar的行”的grep语法,请参阅对多个搜索模式使用grep

#1 楼

agrep可以使用以下语法来做到这一点:

agrep 'pattern1;pattern2'


使用GNU grep,当构建有PCRE支持时,您可以执行以下操作:

grep -P '^(?=.*pattern1)(?=.*pattern2)'


使用ast grep

grep -X '.*pattern1.*&.*pattern2.*'


(将.*添加为<x>&<y>会匹配完全匹配<x><y>的字符串,而a&b将永远不会匹配,因为没有这样的字符串可以同时为ab。)

如果模式不重叠,则还可以:

grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'


最好的便携式方法可能是已经提到的awk

awk '/pattern1/ && /pattern2/'


sed

sed -e '/pattern1/!d' -e '/pattern2/!d'


请注意,所有这些都将具有不同的正则表达式语法。

评论


agrep语法不适用于我...它引入了哪个版本?

–拉曼
2016年9月5日在22:15

1992年的@Raman 2.04已经有了它。我没有理由相信它从一开始就不存在。可以在glimpse / webglimpse中找到较新的(1992年之后)agrep版本。可能您有不同的实现。我对于ast-grep版本有一个错误,增强正则表达式的选项是-X,而不是-A。

–StéphaneChazelas
16-09-6在5:55



@StéphaneChazelas谢谢,我在Fedora 23上有agrep 0.8.0。这似乎是与您引用的agrep不同的agrep。

–拉曼
2016年9月6日下午6:37

@Raman,您的声音听起来像TRE agrep。

–StéphaneChazelas
2016年9月6日7:01

@Techiee,或者只是awk'/ p1 / && / p2 / {n ++}; END {打印0 + n}'

–StéphaneChazelas
17年6月28日在20:23

#2 楼

您未指定grep版本,这一点很重要。一些正则表达式引擎允许使用“&”按AND将多个匹配分组,但这是非标准且不可移植的功能。但是,至少GNU grep不支持此功能。

您可以简单地用sed,awk,perl等替换grep(按重量增加的顺序列出)。使用awk时,命令看起来像

awk '/regexp1/ && /regexp2/ && /regexp3/ { print; }'


,并且可以轻松地在命令行中指定它。

评论


请记住,awk使用ERE,例如等同于grep -E,而不是普通grep使用的BRE。

– jw013
2012年10月10日9:42

awk的正则表达式称为ERE,但实际上它们有点特质。这里可能是比任何人都关心的更多细节:wiki.alpinelinux.org/wiki/Regex

– dubiousjim
2012年11月10日15:35



谢谢grep 2.7.3(openSUSE)。我投票给您,但我将让问题待一会儿,也许grep有一些窍门(不是我不喜欢awk,只是知道更多更好)。

–greenoldman
2012年11月10日15:42



默认操作是打印匹配的行,因此{print; }部分在这里并不是真正必要或有用的。

–tripleee
17-4-20在11:58



#3 楼

如果patterns每行包含一个模式,则可以执行以下操作:

 awk 'NR==FNR{a[awk 'NR==FNR{a[patterns];next}{for(i in a)if(!index(NR==FNR,i))next}1' patterns -
];next}{for(i in a)if(FILENAME==ARGV[1]!~i)next}1' patterns -
 


或它匹配子字符串而不是正则表达式:

 ARGIND==1 


要打印所有而不是没有行如果gawk为空,则输入,用gagai中的ga(){ awk 'FILENAME==ARGV[1]{a[q4312079q];next}{for(i in a)if(!index(q4312079q,i))next}1' <(printf %s\n "$@") -; } gai(){ awk 'FILENAME==ARGV[1]{a[tolower(q4312079q)];next}{for(i in a)if(!index(tolower(q4312079q),i))next}1' <(printf %s\n "$@") -; } 替换q4312079q。这些函数打印STDIN的行,其中包含指定为参数的每个字符串作为子字符串的STDIN行。 q4312079q代表grep all,而q4312079q忽略大小写。

 q4312079q 


评论


明确的答案,解决了几种用例和工作原理(在macOS上验证)

– ShpielMeister
20年8月8日在18:19

#4 楼


grep pattern1 | grep pattern2 | ...
我想使用单个grep,因为我正在动态地构建参数,因此所有内容都必须放在一个字符串中。

实际上可以动态地构建管道(无需采取任何措施)到eval):
 # Executes: grep "" | grep "" | grep "" | ...
function chained-grep {
    local pattern=""
    if [[ -z "$pattern" ]]; then
        cat
        return
    fi    

    shift
    grep -- "$pattern" | chained-grep "$@"
}

cat something | chained-grep all patterns must match order but matter dont
 

这可能不是一个非常有效的解决方案。

评论


使用chained-grep()或函数chained-grep,但不要使用函数chained-grep():unix.stackexchange.com/questions/73750/…

– nisetama
19年1月19日在17:08

您能描述一下窍门吗?您可以通过编辑将其添加到答案中(不带“编辑:”,“更新:”或类似内容)吗?

– Peter Mortensen
20-10-30在20:40



重新设计了答案,使技巧更清晰(即:动态构建外壳管道)

–olejorgenb
20-10-30在23:21

#5 楼

git grep

使用git grep的语法是使用布尔表达式组合多个模式:

git grep --no-index -e pattern1 --and -e pattern2 --and -e pattern3


以上命令将在以下位置打印与所有模式匹配的行


--no-index在当前目录中搜索不受Git管理的文件。


检查man git-grep以获得帮助。

另请参阅:


如何使用grep匹配string1和string2?

检查文件中是否存在所有多个字符串或正则表达式。 br />
有关“或”运算的信息,请参见:


如何对带有管道字符的图案的多个图案进行grep?
Grep:如何添加“ OR”条件?


评论


极好的答案。谢谢。

–穆罕默德·巴纳(Mohamed Bana)
20-10-6在9:22

#6 楼

这是我的看法,适用于多行单词:

使用find . -type f,后跟尽可能多的-exec grep -q 'first_word' {} \;
,最后一个带有-exec grep -l 'nth_word' {} \;的关键字

-q安静/无声-l显示具有匹配项的文件

以下返回其中包含单词“ rabbit”和“ hole”的文件名列表:find . -type f -exec grep -q 'rabbit' {} \; -exec grep -l 'hole' {} \;

评论


如果仔细看,您可能会发现这不是问题所要求的功能。

– G-Man说“恢复莫妮卡”
20 Dec 7'在5:40

#7 楼

ripgrep

下面是使用rg的示例:

rg -N '(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)' file.txt


它是最快的grepping工具之一,因为它是基于Rust的正则表达式引擎构建的它使用有限自动机,SIMD和积极的文字优化来使搜索变得非常快。

另请参阅GH-875上的相关功能要求。

#8 楼

要查找所有单词(或模式),可以在grep循环中运行for。这里的主要优点是从正则表达式列表中搜索。
一个真实的示例:
# File 'search_all_regex_and_error_if_missing.sh'

find_list="\
^a+$ \
^b+$ \
^h+$ \
^d+$ \
"

for item in $find_list; do
   if grep -E "$item" file_to_search_within.txt
   then
       echo "$item found in file."
   else
       echo "Error: $item not found in file. Exiting!"
       exit 1
   fi
done

现在让我们在此文件上运行它:
hhhhhhhhhh
aaaaaaa
bbbbbbbbb
ababbabaabbaaa
ccccccc
dsfsdf
bbbb
cccdd
aa
caa

$ ./search_all_regex_and_error_if_missing.sh
aaaaaaa aa
^a+$ found in file.
bbbbbbbbb bbbb
^b+$ found in file.
hhhhhhhhhh
^h+$ found in file.
Error: ^d+$ not found in file. Exiting!


评论


您的逻辑有误-我要求使用ALL运算符,您的代码用作OR运算符,而不是AND。顺便说一句。因为(OR)是问题中给出的更简单的解决方案。

–greenoldman
18年8月14日在22:18



@greenoldman逻辑很简单:for将在列表中的所有单词/模式上循环,如果在文件中找到它,则将其打印出来。因此,如果您不需要采取措施以防找不到单词,只需删除else即可。

– Noam Manos
18年8月16日在15:07

我理解您的逻辑以及我的问题-我在问AND运算符,这意味着如果文件与模式A和模式B以及模式C和...匹配,则文件仅是肯定命中,并且...它匹配模式A或模式B或...您现在看到区别了吗?

–greenoldman
18年8月17日在6:19

@greenoldman不确定为什么您认为此循环不检查所有模式的AND条件?因此,我用一个真实的示例编辑了我的答案:它将在文件中搜索列表的所有正则表达式,并且在第一个缺失的正则表达式中-会错误退出。

– Noam Manos
18年8月19日在15:04



您将它放在眼前,在执行第一个比赛之后就拥有正面比赛。您应该“收集”所有结果并对其进行计算和。然后,您应该重写脚本以在多个文件上运行-然后,也许您意识到问题已经得到回答,并且您的尝试没有带来任何好处,对不起。

–greenoldman
18年8月20日在5:56