Remove nested quotes

后端 未结 3 1244
無奈伤痛
無奈伤痛 2020-12-20 09:47

I have this text and I\'m trying to remove all the inner quotes, just keeping one quoting level. The text inside a quote contains any characters, even line feeds, etc. Is th

相关标签:
3条回答
  • 2020-12-20 10:30

    use this pattern

    \[quote=?[^\]]*\][^\[]*\[/quote\](?=((.(?!\[q))*)\[/)
    

    and replace with nothing like in this example

    0 讨论(0)
  • 2020-12-20 10:45

    You can use this:

    $result = preg_replace('~\G(?!\A)(?>(\[quote\b[^]]*](?>[^[]+|\[(?!/?quote)|(?1))*\[/quote])|(?<!\[)(?>[^[]+|\[(?!/?quote))+\K)|\[quote\b[^]]*]\K~', '', $text);
    

    details:

    \G(?!\A)              # contiguous to a precedent match
    (?>                   ## content inside "quote" tags at level 0
      (                    ## nested "quote" tags (group 1)
        \[quote\b[^]]*]
        (?>                ## content inside "quote" tags at any level
          [^[]+
         |                  # OR
          \[(?!/?quote)
         |                  # OR
          (?1)              # repeat the capture group 1 (recursive)
        )*
        \[/quote]
      )
     |
      (?<!\[)           # not preceded by an opening square bracket
      (?>              ## content that is not a quote tag
        [^[]+           # all that is not a [
       |                # OR
        \[(?!/?quote)   # a [ not followed by "quote" or "/quote"
      )+\K              # repeat 1 or more and reset the match
    )
    |                   # OR
    \[quote\b[^]]*]\K   # "quote" tag at level 0 
    
    0 讨论(0)
  • 2020-12-20 10:47

    I think it would be easier to write a parser.

    Use regex to find [quote] and [\quote], and then analyse the result.

    preg_match_all('#(\[quote[^]]*\]|\[\/quote\])#', $bbcode, $matches, PREG_OFFSET_CAPTURE);
    $nestlevel = 0;
    $cutfrom = 0;
    $cut = false;
    $removed = 0
    foreach($matches(0) as $quote){
        if (substr($quote[0], 0, 1) == '[') $nestlevel++; else $nestlevel--;
        if (!$cut && $nestlevel == 2){ // we reached the first nested quote, start remove here
            $cut = true;
            $cutfrom = $quote[1];
        }
        if ($cut && $nestlevel == 1){ // we closed the nested quote, stop remove here
            $cut = false;
            $bbcode = substr_replace($bbcode, '', $cutfrom - $removed, $quote[1] + 8 - $removed); // strlen('[\quote]') = 8
            $removed += $quote[1] + 8 - $cutfrom;
        }
    );
    
    0 讨论(0)
提交回复
热议问题