为什么 grep 匹配得比它应该的多,例如 "^[s]*set breakpoint.*in"匹配"set breakpoint 1 at main.c:5" ?



patterns.txt

^[s]*set breakpoint.*if
^[s]*set breakpoint.*in
^[s]*set breakpoint.*skip

脚本.txt

set breakpoint 1 at main.c:5
set breakpoint 2 at main.c:6
set breakpoint 3 at main.c:7
set breakpoint 4 if

示例和意外结果

当我运行cat "${script.txt}" | grep -f patterns.txt时,结果是:

set breakpoint 1 at main.c:5 // WHY DOES THIS MATCH???
set breakpoint 2 at main.c:6 // WHY DOES THIS MATCH???
set breakpoint 3 at main.c:7 // WHY DOES THIS MATCH???
set breakpoint 4 if

同样适用于:

cat "${script.txt}" | grep -E '^[s]*set breakpoint.*if|^[s]*set breakpoint.*in|^[s]*set breakpoint.*skip'

这是因为breakpoint.*in在前 3 行中匹配breakpoint <digit> at mainmainin 结尾)。

您应该在模式中使用结束锚点,如下所示:

cat patterns.txt
^s*set breakpoint.*if$
^ss*et breakpoint.*in$
^ss*et breakpoint.*skip$

否则:

^s*set breakpoint.*i[fn]$
^ss*et breakpoint.*skip$

贪婪的表达式

^[\s]*设置断点。

你的正则表达式太贪婪了。 .*通常是问题所在,因为它会消耗尽可能多的内容,其中包括"main"中的"in"。你需要一个不那么贪婪的表达,以及一个更精确的模式。

使用单词边界

使表达式不那么贪婪的一种方法是让模式将单词边界与b原子匹配。例如,在模式中的关键字之前添加单词边界.txt如下所示:

^[s]*set breakpoint.*bif
^[s]*set breakpoint.*bin
^[s]*set breakpoint.*bskip

然后,当您运行扩展的 grep 时,您将只获得您可能期望的输出:

$ egrep -f pattern.txt script.txt 
set breakpoint 4 if

最新更新