Вращающееся регулярное выражение имеет небольшую ошибку

У нас возникли некоторые проблемы с этим регулярным выражением.

/\(\((((?>[^\(\(\)\)]+)|(?R))*)\)\)/x

Он используется для «раскручивания» текстов. Когда у нас есть предложение типа «((Мы ((любим | любим)) эту рубашку (размер xl)))», то он не может реализовать это право. Из-за трех скобок в конце предложения (потому что первая из трех последних скобок в конце принадлежит самому тексту).

Как это должно работать: регулярное выражение должно получить первые 2 скобки, если в начале у него 3 или более скобок, и закрыть последние 2, если в конце есть 3 или более скобок. Это возможно???

имейте в виду, что теперь это работает довольно хорошо на многоуровневом уровне, поэтому что-то вроде "((это((рубашка|свитер))))" работает хорошо (см. 4 круглые скобки в конце?). Таким образом, это происходит только тогда, когда круглые скобки, которые принадлежат тексту, начинаются сразу после начальных круглых скобок для вращения ИЛИ заканчиваются прямо перед конечными скобками.


person Erik van de Ven    schedule 09.10.2013    source источник


Ответы (1)


Ну, во-первых, вам не нужно экранировать круглые скобки внутри классов символов, и не более полезно помещать один и тот же символ в класс символов более одного раза; таким образом, ваше регулярное выражение может стать таким без каких-либо изменений в функциональности:

\(\((((?>[^()]+)|(?R))*)\)\)

Я тоже не совсем понимаю, почему вы используете атомную группу; Я могу ошибаться (и поправьте меня, если я ошибаюсь), но я не нахожу никакой разницы, кроме использования стандартной группы без захвата.

Тем не менее, теперь вы можете разрешить вложенные строки с одинарными скобками в регулярном выражении, включив другую возможность во внутренний захват регулярного выражения:

\(\(((?:[^()]|((?R))|(\((?:[^()]|(?3))*\)))*)\)\)
    1         2      3

Группы захвата:
1 – получает первое большое совпадение между самыми внешними (( ... ))
2 – получает внутренние совпадения и любые другие вложенные (( ... ))
3 – получает содержимое между одиночными скобками, чтобы в этой группе была разрешена рекурсия. также. Если он вам не нужен, просто проигнорируйте его в массиве, он нужен только для того, чтобы разрешить вложенные одиночные скобки.

демонстрационная версия regex101

person Jerry    schedule 09.10.2013
comment
Ты мой герой! Последнее регулярное выражение (\(\(((?:[^()]|((?R))|(\((?:[^()]|(?3))*\)))*)\)\)) работает как шарм!!!! - person Erik van de Ven; 15.10.2013
comment
@ErikVandeVen Я просто пытался помочь ^^; Я рад, что это сработало для вас :) - person Jerry; 16.10.2013