Книга: Программирование на языке Ruby

3.13.7. Рекурсия в регулярных выражениях

3.13.7. Рекурсия в регулярных выражениях

Возможность повторно обращаться к подвыражению позволяет создавать рекурсивные регулярные выражения. Например, данный код находит любое вложенное выражение с правильно расставленными скобками (спасибо Эндрю Джексону):

str = "а * ((b-c)/(d-e) - f) * g"
reg = /(?         # Начало именованного выражения.
       (         # Открывающая круглая скобка.
        (?:       # Незапоминаемая группа.
         (?>      # Сопоставление с собственническим выражением:
           [()] # экранированная скобка
          |       # ЛИБО
           [^()]  # вообще не скобка. )
          )       # Конец собственнического выражения.
          |       # ЛИБО
          g      # Вложенная группа в скобках (рекурсивный вызов).
         )*       # Незапоминаемая группа повторяется нуль или
                  # более раз.
        )        # Закрывающая круглая скобка.
       )          # Конец именованного выражения.
      /x
m = reg.match(str).to_a # ["((b-c)/(d-e) - f)", "((b-c)/(d-e) - f)"]

Отметим, что левосторонняя рекурсия запрещена. Следующий пример допустим:

str = "bbbaccc"
re1 = /(?<foo>a|bg<foo>c)/
re1.match(str).to_a # ["bbbaccc","bbbaccc"]

А такой — нет:

re2 = /(?<foo>a|g<foo>c)/ # Синтаксическая ошибка!

Ошибка объясняется наличием рекурсивного обращения в начале каждой альтернативы. Немного подумав, вы поймете, что это приведет к бесконечному возврату.

Оглавление книги


Генерация: 1.169. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз