RegEx:嵌套标签

时间:2014-11-21 15:37:42

标签: javascript php regex preg-replace nested-loops

我使用正则表达式,但我无法为我的情况做这件事。我已经创建了像DLE这样的引擎。 我有[a],[/ a],[b],[/ b]等标签。我使用正则表达式

'\\[a\\](.*?)\\[/a\\]'si 

或喜欢

'\\[a\\](.*?)(\\[/a\\])+'si

它不能按我的意愿行事。 我需要收到:

from '[a]delete[/a]' : ''

from '[a][b]delete[/b][/a]' : '',

from '[a][a]delete[/a][/a]' : '', with '\\[a\\](.*?)\\[/a\\]'si it returns '[/a]'

from '[b][a]delete[/a][b]' : '[b][/b]'

from '[b][a]delete[/a][b] [a]delete[/a]' : '[b][/b]'

from '[a]
          delete
          [a]
              [b]delete[/b]
          [/a]
          delete
      [/a]
      [b]
          [a]delete[/a]
          nodelete
      [/b]'
      :
      '[b]
          nodelete
      [/b]'

帮我创建正确的正则表达式!

1 个答案:

答案 0 :(得分:2)

PHP方式

你可以用php一次性完成。但是要处理嵌套标签,你需要使用递归功能,所以你不能用Javascript做同样的事情:

$text = preg_replace('~\s*\[a](?:[^[]+|\[(?!/?a])|(?R))*+\[/a]\s*~', '', $text);

online demo

模式详情

~                  # pattern delimiter
\s*                # only here to remove leading whitespaces
\[a]
(?:                # non-capturing group: describes the allowed 
                   # content between tags:
    [^[]+          #    - all that is not a [
  |                #  OR
    \[ (?!/?a])    #    - a [ that is not the begining of an opening
                   #       or closing "a" tag
  |                #  OR
    (?R)           #    - recurse to the whole pattern
)*+                # repeat the group zero or more times (possessive quantifier)
\[/a]
\s*                # to remove trailing spaces
~

Javascript方式

由于递归功能不适用于ECMAScript正则表达式引擎,因此解决问题的方法是使用几次替换目标,这些替换目标是最内层的" a"标签。要完成此任务,您可以使用此模式禁止嵌套" a"标签(请注意,该模式与之前的模式非常相似,语法(?=(subpattern*))\1仅模拟占有量词)

text = text.replace(/\s*\[a\](?=((?:[^\[]+|\[(?!\/?a\]))*))\1\[\/a\]\s*/g, '');

您需要应用此替换,直到无法替换更多标记。您可以使用闭包作为替换来检测替换的数量,从而递增计数器,然后将所有替换放在do...while循环中。例如:

var counter;    
do {
    counter = 0;
    text = text.replace(/\s*\[a\](?=((?:[^\[]+|\[(?!\/?a\]))*))\1\[\/a\]\s*/g, function (m) {counter++; return '';});
} while (counter>0)