perl regex - 如何匹配不以 (\s*//\s*) 开头的 foobar

perl regex - 如何匹配不以 (\s*//\s*) 开头的 foobar

基本上我想在未注释的行上找到 foobar,例如:

// foobar      # do not match me
 foobar        # match me
 otherfoobar   # do not match me

为了匹配注释行,我使用这个:^(\s*//\s*)\bfoobar\b.*$

如何匹配未注释的行?

笔记:

为了避免不必要的努力,请将答案限制为“^...$”。这必须纯粹在发送到 perl 进行匹配的字符串内完成。

另外 foobar 必须整体匹配,如 \bfoobar\b

最后, \bfoobar\b 前面不应该有任何东西,除了空格或注释签名。

答案1

foobara 右侧未找到的 a可以//表示为:

^(?:(?!//).)*\bfoobar\b

*这是一个由 0 个或多个 ( ) 个字符 ( )组成的序列,每个字符都不位于序列 ( ).的开头,后跟由单词边界分隔的字符。//(?!//)foobar

答案2

如果您使用的是 Perl(语言),而不是使用与 Perl 兼容的正则表达式的工具,则没有理由将自己限制为仅使用一个正则表达式。

像这样的东西只会匹配未注释的行:

$ perl -ne 'print if not m,^\s*//, and /\bfoobar\b/' < file.txt 
 foobar        # match me

即使使用其他实用程序或非 Perl 正则表达式,仅使用多个正则表达式可能是最简单的:

$ < file.txt grep -ve '//' | grep '\<foobar\>'
 foobar        # match me

相反,如果您仅限于单个 Perl 正则表达式,那么这应该可以工作:

grep -P '^\s*+(?!//).*\bfoobar\b.*$' file.txt

\s*+是一个“占有欲”表达,它匹配所有前导空格,并且不放开他们。然后(?!//)检查前导空格后面的内容是否不是注释标记,最后我们foobar在该行的任何位置查找断字内。

(如果在没有所有格限定符的情况下匹配空白,则正则表达式引擎可能会从前导空白中退出,并检查错误位置的注释标记,从而导致注释行被匹配。)

测试数据:

$ cat file.txt
 // foobar        # do not match
 foobar           # 1st match
otherfoobar       # do not match
something foobar  # 2nd and final match
$ grep -P '^\s*+(?!//).*\bfoobar\b.*$' file.txt
 foobar           # 1st match
something foobar  # 2nd and final match

答案3

我认为否定的问题不应该过于复杂。

例如说我想拒绝这些行:

"^(\s*//\s*).*(\bfoobar\b).*$"

IE。'//'在开头的空白处有注释签名,后跟包含'foobar'整个单词的任何内容(为了清楚起见,包含括号)。

为了否定这一点,我们这样做:

"^(?!\s*//\s*).*(\bfoobar\b).*$"

我们只是替换(\s*//\s*)(?!\s*//\s*)

'//'这会忽略开头处的空白处具有注释签名的任何内容,后跟我们的模式。

结果:

  // foobar will not be matched
  // whatever foobar will not be matched
  foobar will be matched
  whatever foobar will be matched
  whateverfoobar will not be matched

笔记:.*您可以通过更改之前的(\bfoobar...设置来进一步微调。

例如我可以做"^(?!\s*//\s*)\s*(\bfoobar\b).*$"

  foobar will be matched
  whatever foobar will **NOT** be matched

警告:'foobar'如果你用一些任意的字符串 替换,比如'${foobar}'你尝试上面的方法,它将会失败。原因是因为您正常的“foobar”仅由单词字符组成,现在(\bfoobar\b)将不匹配它。在这种情况下,\b必须去除。

相关内容