I use regexp, but I cant do it for my case. I have create own engine like DLE. I have tags like [a],[/a],[b],[/b] etc. I use regexp like
'\\[a\\](.*?)\\[/a\\]'si
or like
'\\[a\\](.*?)(\\[/a\\])+'si
and it don't work how I want. I need receive:
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]'
Help me to create right regexp!
PHP way
You can do it in one pass with php. But to deal with nested tags, you need to use the recursion feature, so you can't do the same with Javascript:
$text = preg_replace('~\s*\[a](?:[^[]+|\[(?!/?a])|(?R))*+\[/a]\s*~', '', $text);
pattern details
~ # 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 way
Since the recursion feature is not available for the ECMAScript regex engine, a way to solve the problem is to use several pass of replacements that targets the innermost "a" tags. To accomplish this task you can use this pattern that forbids nested "a" tags (note that the pattern is very similar to the previous, the syntax (?=(subpattern*))\1
only emulates a possessive quantifier):
text = text.replace(/\s*\[a\](?=((?:[^\[]+|\[(?!\/?a\]))*))\1\[\/a\]\s*/g, '');
You need to apply this replacement until there is no more tags to replace. You can detect the number of replacements using a closure as replacement that increments a counter, then you put all in a do...while
loop. Example:
var counter;
do {
counter = 0;
text = text.replace(/\s*\[a\](?=((?:[^\[]+|\[(?!\/?a\]))*))\1\[\/a\]\s*/g, function (m) {counter++; return '';});
} while (counter>0)