我正在尝试匹配配置中以“deny”开头但不以“log”结尾的行。这看起来非常初级,但我在我看过的众多论坛中都找不到我的解决方案。我的初学者心态让我尝试“^deny.* (?!log$)” 为什么这不起作用?我的理解是,它会找到以“拒绝”开头的任何字符串,后跟 0 位或更多位的任何字符,其中行尾不是日志。
问问题
571 次
2 回答
2
当给出类似的行时deny this log
,您的^deny.*(?!log$)
正则表达式(我省略了示例问题中的空格)的评估如下:
^deny
匹配“拒绝”。.*
意思是“匹配0个或多个任意字符”,所以可以匹配“这个日志”。^(?!log$)
意思是“确保下一个字符不是'log'然后是行尾。” 在这种情况下,它们不是——它们只是行尾——所以正则表达式匹配。
试试这个正则表达式:
^deny.*$(?<!log)
“在字符串的开头匹配拒绝,然后匹配到行尾,然后使用零宽度否定后向断言来检查我们刚刚在行尾匹配的内容不是'log'。”
说了这么多……
正则表达式不一定是这项工作的最佳工具。在这种情况下,一个简单的布尔运算符如
if (/^deny/ and not /log$/)
可能比更高级的正则表达式更清晰
if (/^deny.*$(?<!log)/)
于 2013-02-25T19:15:05.327 回答
1
(?!log$)
是一个零宽度的负前瞻断言,这意味着如果在字符串中的这一点立即向前,则不匹配是log
和字符串的结尾,但是.*
您的正则表达式中的 已经贪婪地消耗了所有字符直到结束的字符串所以没有办法log
可以匹配。
如果您的正则表达式实现支持后视,您可以使用 Josh Kelley 的回答中的正则表达式,如果您使用的是 javascript,您可以使用
/^deny(?:.{0,2}|.*(?!log)...)$/m
该m
标志表示多行模式,它创建^
并$
匹配每行的开始和结束,而不仅仅是字符串的开始和结束。
请注意,三个.
位于负前瞻之后,以便它有空间匹配log
(如果它在那里)。包括这三个点意味着还需要添加.{0,2}
选项,以便后面从零到两个字符的字符串deny
也将匹配。这意味着a或b必须匹配(?:a|b)
的非捕获组。
于 2013-02-25T19:29:39.863 回答