【问题标题】:Why does this Regex match even though it should fail?为什么这个正则表达式匹配,即使它应该失败?
【发布时间】:2014-12-12 14:14:13
【问题描述】:

当 URL 的格式为“msgID”或“msg=ID”时,我想提取消息 ID 的第一个实例,但在“msg”和“ID”之间有任何其他字符时不提取

应该给我消息 ID 的测试字符串:

/forum/index.php/topic,101126.msg3826887.html#msg3826887
/forum/index.php?topic=101126.msg3826887#msg3826887
/forum/index.php?msg=3826887

应该失败的测试字符串:

/forum/index.php?msgrad3826887
/forum/index.php?msg,3826887

这是我的正则表达式:

forum\/index.php.+?msg=?([0-9]*)

但是,当我在RubularRegexr 中测试它时,它们显示正则表达式成功匹配所有这些字符串。

应该失败的测试不会为捕获组提供任何结果,但在其他方面似乎匹配成功。

为什么会发生这种情况,我该如何修复我的正则表达式?

【问题讨论】:

  • 你在哪里使用这个?重写规则? PHP 代码?
  • .+? 是否导致它查找非空格字符的任意组合一次或多次?
  • @nhahtdh Nginx 重写规则

标签: regex nginx pcre


【解决方案1】:

您的正则表达式匹配无效字符串,因为 ID 是可选的:[0-9]* 可以匹配空字符串。

只需将* 替换为+ 即可要求至少一位数字。

顺便说一句,这是一个改进的版本:

forum\/index\.php.+?\bmsg=?(\d+)

Demo

您应该已经逃脱了.。我还在msg 之前添加了\b,以确保msg 不是较长单词的一部分。请注意,在正则表达式的意义上,转义 / 不是必需的,但您的语言/工具可能需要它。

【讨论】:

  • 我以前从未见过\b 开关,谢谢分享改进
  • @Jeff 这是一个零宽度断言,大致相当于(?:(?<!\w)(?=\w)|(?<=\w)(?!\w))。它确保它出现的位置是单词边界(如果字符与\w 匹配,它会将字符视为单词的一部分)。
猜你喜欢
  • 2010-12-10
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 1970-01-01
  • 2013-04-19
相关资源
最近更新 更多