регулярное выражение, чтобы извлечь взгляд назад и взгляд из шаблона регулярного выражения - PullRequest
1 голос
/ 02 февраля 2020

У меня есть необычное приложение, в котором мне нужно извлечь содержимое частей просмотра и просмотра шаблона регулярного выражения (конечно же, используя регулярное выражение!). Например, в следующем шаблоне:

(?<=(?:c|d))123(?=(?:x|y))

соответствует первому 123 в следующей строке:

abc123xyz123xyz

Мне нужно извлечь следующие строки:

(?:c|d)

и

(?:x|y)

Это сложно, потому что я не могу легко найти правильные закрывающие скобки, так как могут быть другие скобки, как в примере.

Просто интересно, приходилось ли кому-то делать это раньше. Любые мысли приветствуются

1 Ответ

1 голос
/ 16 февраля 2020

Исходя из комментариев к вопросу, я понимаю, что asker Kaveh1000 доволен решением Wiktor; однако кажется, что он озадачен одной частью этого решения

(\((?:[^()]++|(?1))*\))

В этом отношении я предлагаю прочитать Освоение регулярных выражений, 3-е издание , которое посвящает много слов этой теме. c (и именно к этому самому регулярному выражению); Я только что прочитал это оттуда сейчас, и в следующем я пытаюсь передать свое понимание:

  1. это группа захвата (…), к которой мы можем обратиться, если нам нужно (и мы делаем действительно в 4.2.);
  2. это соответствует паре буквального паретеза с чем-то между \(…\);
  3. , что что-то между, (?:…)*, является последовательностью 0 или более ( обычные жадные) неперехваченные выражения;
  4. каждое из этих 0 или более повторений может быть либо

    4.1. последовательность из 0 или более, не являющаяся скобками, [^()]++,

    4.2. или что-то, (?1), что соответствует тому же регулярному выражению, которое мы сейчас сопоставляем (точка 1); это рекурсивность регулярного выражения.

Два примечания:

  • Буквенные скобки появляются в (этой части) регулярного выражения только через \( и \), которые упорядочены (сначала открытие, затем закрытие) и оба должны совпадать; это гарантирует, что эта часть регулярного выражения будет соответствовать только сбалансированному паретизу.
  • ++ необходимо, потому что, если регулярное выражение равно ((something)+)*, есть много способов присвоить количество повторений + и * и всех их нужно судить; ++ вместо + будет соответствовать в максимально возможной степени, как это было в (something)+, и только тогда * вступает в силу.
  • Но что само по себе ++? Я имею в виду, что ++ за пределами причины, почему это необходимо в этом регулярном выражении? Один простой способ выделить и ясно увидеть влияние ++ по сравнению с + - сравнить поведение регулярных выражений a+ab и a++ab со строкой, содержащей aaaaaab. Первый будет соответствовать всей строке: a+ соответствует первым 5 a с и ab соответствует последним двум символам; последний не будет совпадать, так как a++ соответствует как можно большему числу a с, не уступая в пользу остальной части регулярного выражения, тем самым сопоставляя все 6 a, не оставляя шансов для ab совпадения после это и, в конечном итоге, приводит к провалу матча.
...