正则表达式:嵌套标签


RegEx: nested tags

我使用正则表达式,但我不能为我的情况做到这一点。我创建了自己的引擎,如 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]'

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

PHP 方式

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

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

在线演示

图案详细信息

~                  # 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)