grep -w 仅匹配行中模式的第一次出现

avi*_*iro 5 grep regular-expression

我试图理解为什么grep -w(GNU 实现的版本 3.1)仅匹配一行中特定模式的第一次出现。

这是一个例子。我希望它会匹配n1,n2n3,但它只匹配第一个。

$ echo 'n1=1 n2=2 n3=3' | grep -ow "n[0-9]=*"
n1
Run Code Online (Sandbox Code Playgroud)

或者,如果我告诉它仅匹配n2n3,它再次匹配第一个,并忽略n3

$ echo 'n1=1 n2=2 n3=3' | grep -ow "n[23]=*" 
n2
Run Code Online (Sandbox Code Playgroud)

我在这里缺少什么?对于这种行为有任何解释吗,或者这是 grep 中的某种错误?

这个想法是匹配:

  1. n[0-9]前面和后面都是非单词字符。
  2. 以 开头,后跟n[0-9]任意数量的=字符,以非单词字符结尾的子字符串。

例如,如果字符串是n1=1 n2=== n3=3 n4== n5,则预期结果应该是:

n1
n2===
n3
n4==
n5
Run Code Online (Sandbox Code Playgroud)

澄清:我知道目标可以通过 实现grep -ow -e 'n[0-9]' -e "n[0-9]=*",但这不是重点。该问题的目的是了解如何grep工作。

加法测试

如果我添加n<num>=到行中的不同位置(等号后没有后续单词字符),它也会匹配这些字符,但它会再次忽略n3=3.

$ echo 'n1=1 n2= n3=3 n4=' | grep -ow "n[0-9]=*"
n1
n2=
n4=
Run Code Online (Sandbox Code Playgroud)

我发现的最后一件事是,如果我添加-P将模式解释为与 Perl 兼容的正则表达式,它似乎不会保留-w子字符串“必须位于行尾或后面”的描述由非单词构成字符",因为n1=即使它后面跟着字符1,它也是匹配的,字符 1 是单词构成字符(“字母、数字和下划线”)。

$ echo 'n1=1 n2= n3=3 n4=' | grep -owP "n[0-9]=*"
n1=
n2
n3=
n4
Run Code Online (Sandbox Code Playgroud)

所以看起来是在子字符串末尾grep -wP搜索单词边界而不是非单词组成字符。它似乎相当于:

$ echo 'n1=1 n2= n3=3 n4=' | grep -o "\bn[0-9]=*\b"
n1=
n2
n3=
n4
Run Code Online (Sandbox Code Playgroud)

pLu*_*umo 3

接得好。这似乎确实是一个错误grep (用 3.4 和 3.7 测试GNU grep):

grep -ow "n[0-9]=*"
grep -Eow "n[0-9]=*"
Run Code Online (Sandbox Code Playgroud)

仅返回第一个匹配项(或者可能只匹配第一个匹配项),
而...

grep -Pow "n[0-9]=*"
Run Code Online (Sandbox Code Playgroud)

...按预期返回所有匹配项。

要报告错误GNU grep,请检查此处


但是,我无法确认您的观察结果,即-P[...] 似乎没有保留-w说明,对我来说(GNU grep 3.4 和 3.7),该命令按预期输出:

$ echo 'n1=1 n2= n3=3 n4=' | grep -owP "n[0-9]=*"
n1
n2=
n3
n4=
Run Code Online (Sandbox Code Playgroud)