PHP/PCRE 正则表达式以递归模式开头

PHP/PCRE regex starts with on recursive pattern

我正在尝试将降价标签与递归相匹配。

输入语法

(TYPE: VALUE ATTR_KEY: ATTR_VALUE)

请注意,语法应以:[a-z0-9_-]+:

开头

示例输入:

(image: sky.jpg)
(image: sky.jpg caption: Sky (Issue This) View)
(link: https://whosebug.com text: Stack Overflow)
(link: https://whosebug.com text: Stack Overflow rel=nofollow)
(video: http://www.youtube.com/watch?v=49Kh1mS4Fhs)

当前使用以下正则表达式:

(?=[^\]])\([a-z0-9_-]+:.*?\)

但问题来自这里,因为匹配:

(image: sky.jpg caption: Sky (Issue This)

预期匹配:

(image: sky.jpg caption: Sky (Issue This) View)

如果括号中再次使用括号,则不完全匹配。

我试过遵循递归模式并且有效,但我需要限制以字符开头。

(?s)\((?:[^()]+|(?R))*+\)
\((?:[^)(]+|(?R))*+\)

您应该使用积极的前瞻来匹配确保匹配以该模式开始,但是您必须将整个括号匹配模式包装在另一个捕获组中并使用 (?1) subroutine 而不是 (?R) 只递归那个模式,而不是整个正则表达式:

(?=\([a-z0-9_-]+:)(\((?:[^()]+|(?1))*+\))
^^^^^^^^^^^^^^^^^^^            ^^^^     ^

参见regex demo

详情

  • (?=\([a-z0-9_-]+:) - 正向前瞻,需要 (、1+ 个小写 ASCII 字母、数字、下划线或连字符后跟 :,紧接在当前位置
  • (\((?:[^()]+|(?1))*+\)) - 捕获第1组(稍后会递归):
    • \( - (
    • (?:[^()]+|(?1))*+ - 1+ 重复 1+ 除 () 以外的任何字符或整个第 1 组模式(递归)
    • \) - )

如果您还想支持笑脸,您可以在正则表达式子例程所在的交替组中添加它们的特定模式,作为第一个选择:

(?=\([a-z0-9_-]+:)(\((?::[)(]|[^()]|(?1))*+\))
                        ^^^^^  

我添加 :[)(] 匹配 :):( 并从 [^()] 之后删除 + 以便能够检查嵌套内的字符串括号逐个字符。

随时根据您的需要进行调整,或添加

使用 (?=\([a-z0-9_-]+:)(\((?::(?:[()pPDd*oO]|'\()|<3|;\)|[^()]|(?1))*+\)) 正则表达式参见 this regex demo