【问题标题】:Matching BBcode inside another bbcode (same tag)在另一个 bbcode 中匹配 BBcode(相同的标签)
【发布时间】:2014-08-20 18:19:09
【问题描述】:

正则表达式:http://regex101.com/r/uO6jQ3/1

字符串:

[quote]something [quote]something else[/quote] some text here[/quote]

当前正则表达式匹配的内容:

$matches[6][0]:[quote]something [quote]something else[/quote]

应该匹配什么:

$matches[6][0]:[quote]something [quote]something else[/quote] some text here[/quote]

$matches[6][1]:[quote]something else[/quote]

【问题讨论】:

  • 不要使用正则表达式解析 HTML/BBCode/XML。这是禁止的。
  • 对不起,正则表达式不能那样工作。
  • @hsz:不被禁止,但绝对“无法处理所有可能的 bbcode 标记组合”。
  • 小心尝试使用正则表达式解析嵌套标签。可以召唤unholy ponies
  • 你想做什么,递归解析嵌套的[quote][/quote] 沿途取出内容,构建哈希树还是?同时检查错误?当然可以使用正则表达式来完成。

标签: php regex bbcode


【解决方案1】:

要匹配嵌套结构,需要递归模式,例如:

$data = '[quote]something [quote]something else[/quote] some text here[/quote]';

$pattern = '~\[quote](?>[^][]+|(?R))*\[/quote]~';

if (preg_match_all($pattern, $data, $m))
    print_r(m);

图案细节:

~           # pattern delimiter: do not choose the slash here
\[quote]    #
(?>         # open an atomic group: possible content between tags
    [^][]+  # all that is not a square bracket
  |         # OR
    (?R)    # recurse the whole pattern
)*          # close the atomic group, repeat zero or more times
\[/quote]   #
~

请注意,这很容易。但是现在如果你的代码可能在“quote”标签之间包含其他寄生虫标签,你只需要更改原子组以允许它们(以扩展模式编写)

(?> [^][]+ | \[/? (?!quote\b) [^]]* ] | (?R) )*

【讨论】:

    【解决方案2】:

    如果您觉得雄心勃勃,您可以坐在 while 搜索循环中并构建一个嵌套的内容数组。每个匹配的新核心都需要对执行此正则表达式的解析函数进行可重入调用。

     # //////////////////////////////////////////////////////
     # // The General Guide to 3-Part Recursive Parsing
     # // ----------------------------------------------
     # // Part 1. CONTENT
     # // Part 2. CORE
     # // Part 3. ERRORS
    
     (?is)
    
     (?:
          (                                  # (1), Take off CONTENT
               (?&content) 
          )
       |                                   # OR
          \[quote\]                          # Start-Delimiter
          (                                  # (2), Take off The CORE
               (?&core) 
            |  
          )
          \[/quote\]                         # End-Delimiter
    
       |                                   # OR
          (                                  # (3), Take off Unbalanced (delimeter) ERRORS
               \[/?quote\]
          )
     )
    
     # ///////////////////////
     # // Subroutines
     # // ---------------
    
     (?(DEFINE)
    
          # core
          (?<core>
               (?>
                    (?&content) 
                 |  
                    \[quote\]
                    # recurse core
                    (?:
                         (?= . )
                         (?&core) 
                      |  
                    )
                    \[/quote\]
               )+
          )
    
          # content 
          (?<content>
               (?>
                    (?!
                         \[/?quote\]
                    )
                    . 
               )+
          )
    
     )
    

    【讨论】:

    • 你的模式有些奇怪,在(?&amp;core) 之后有一个管道,可能是一个错字。或者让(?&amp;core) 成为可选的方法?
    • 不是拼写错误,它要求功能匹配某些东西,这会强制所有交替被击中。所以我们在这里给核心一个通过,因为它也只有它可以是空的。
    • 顺便说一句,核心函数调用之前的 (?= . ) 是 Boost 正则表达式解决方法,否则它会抛出 endless recursion。我经常使用 Boost,不用说有很多解决方法。
    • 我明白了,但是,如果我没记错的话,你不需要用(?=.) 来防止无限递归(这是为了确保至少有一个字符) 因为(?&amp;content)(?&amp;core) 都不能匹配空字符串。 (?&amp;content) 至少有一个字符,(?&amp;core)(?&amp;content)[quote]...[/quote]
    • 您对其他非 Boost 引擎(如 Perl 或 PHP)是正确的。 Boost 人 Jonh Maddok 并没有走得更远(即在下游寻找|
    【解决方案3】:

    您必须构建一个树形结构。查看 CodeProject 上的 STML ParserSTML Parser

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多