具有负面外观和未知中段PHP

时间:2018-04-12 13:07:35

标签: php regex url

在PHP中执行preg_match我使用以下正则表达式:

/\/(bp|s)?\d+\//

这正确匹配以下字符串:

  1. /v/test/bp21/
    • 匹配:/bp21/
  2. /v/test/s21/
    • 匹配:/s21/
  3. /v/test/21/
    • 匹配:/21/
  4. 如果字符串以/cp/开头,我现在想停止匹配,我认为这就像添加负面的lookbehind一样简单:

    /(?<!^\/cp\/)\/(bp|s)?\d+\//

    然而,这似乎不起作用,而是我得到以下结果:

    1. /v/test/bp21/
      • 匹配:/bp21/
    2. /v/test/s21/
      • 匹配:/s21/
    3. /v/test/21/
      • 匹配:/21/
    4. /cp//123123/
      • 不匹配(预期效果)
    5. /cp/test/123123/
      • 已匹配:/123123/ - 不受欢迎
    6. 我猜这是因为我没有在lookbehind和main表达式之间指定任何内容,但字符串可以包含/cp/之后和{{1之前的任意数量的字符例如。

      以下是RegExr上的示例:https://regexr.com/3npis

      我已经尝试过/21/和懒惰量词的大量变体,但我似乎无法将其发现,是否有其他人成功克服了这一点?谢谢!

1 个答案:

答案 0 :(得分:2)

请注意,以下正则表达式使用/以外的字符作为PHP中模式的分隔符。下面的regex101链接使用~作为分隔符。这是为了防止需要转义所有/(因为它们在此正则表达式中很常见)。

See regex in use here

^(?!/cp/).*\K/(?:bp|s)?\d+/
^(?!/cp/).*/(?:bp|s)?\d+/     # If you're just doing boolean operations
^(?!/cp/).*\K/(bp|s)?\d+/     # If you want to capture bp or s
  • ^在行首处断言位置
  • (?!/cp/)否定前瞻确保/cp/不遵循
  • .*多次匹配任何字符
  • \K重置报告的匹配的起点。最终匹配中不再包含任何以前消费的字符
  • /按字面意思匹配
  • (?:bp|s)?可选择匹配bps
  • \d+匹配一个或多个数字
  • /按字面意思匹配

结果:

/v/test/bp21/      # Matches /bp21/
/v/test/s21/       # Matches /s21/
/v/test/21/        # Matches /21/
/cp//123123/       # Does not match
/cp/test/123123/   # Does not match