Регулярные выражения с обратными ссылками — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Правки)
Строка 1: Строка 1:
 
{{Определение
 
{{Определение
 
|id=maindef
 
|id=maindef
|definition='''Регулярные выражения с обратными ссылками''' (англ. ''regex with backreferences'') {{---}} одна из разновидностей регулярных выражений, дающая возможность использовать в них слова, принадлежащие некоторой группе (англ. ''capture group'').
+
|definition='''Регулярные выражения с обратными ссылками''' (англ. ''regex with backreferences'') {{---}} одна из разновидностей регулярных выражений, дающая возможность использовать в них слова, принадлежащие некоторой группе.
 
}}
 
}}
Выражение, заключённое в скобки, называется ''группой''. Скобки захватывают текст, сопоставленный регулярным выражением внтури нумерованной группы, который может быть повторно использован с помощью обратной ссылки с указанием номера группы.
+
<tex>(aba)c\backslash 1</tex> {{---}} пример такого регулярного выражения.
 +
 
 +
Выражение, заключённое в скобки, называется ''группой'' (англ. ''capture group''). Скобки захватывают текст, сопоставленный регулярным выражением внутри нумерованной группы, который может быть повторно использован с помощью обратной ссылки с указанием номера группы.
 +
 
 +
«<tex>\backslash</tex>» – символ обратной ссылки (англ. ''backreference''), который действует на первую группу. Обратная ссылка <tex>\backslash 1</tex> показывает, что после группы <tex>1</tex> {{---}} <tex>(aba)</tex> {{---}} и символа <tex>c</tex> должен быть описан тот же текст, что содержится в ней.
  
 
Порядок нумерации групп: сначала внешняя, потом вложенные (в порядке [[Обход в глубину, цвета вершин|обхода в глубину]]).
 
Порядок нумерации групп: сначала внешняя, потом вложенные (в порядке [[Обход в глубину, цвета вершин|обхода в глубину]]).
==Применение==
 
С помощью обратных ссылок можно составить регулярные выражения для языка тандемных повторов и других языков, где требуется «запоминать» части входящих в язык слов.
 
 
Регулярные выражения в языках программирования зачастую поддерживают обратные ссылки. На практике их можно использовать, например, для парсинга html-выражений (поиск подстрок, содержащихся в определённых тегах).
 
 
==Примеры==
 
==Примеры==
 
* Запишем [[Регулярные языки: два определения и их эквивалентность|регулярное выражение]] для языка тандемных повторов над алфавитом <tex>\Sigma=\{0,1\}</tex>:
 
* Запишем [[Регулярные языки: два определения и их эквивалентность|регулярное выражение]] для языка тандемных повторов над алфавитом <tex>\Sigma=\{0,1\}</tex>:
  
:<tex>L=((0|1)^∗)\backslash 1,</tex>
+
:<tex>L=((0|1)^∗)\backslash 1</tex>
 
 
:где «<tex>\backslash</tex>» – символ обратной ссылки, который действует на первую группу. Обратная ссылка <tex>\backslash 1</tex> показывает, что после группы <tex>1</tex> {{---}} <tex>((0|1)^∗)</tex> {{---}} должен быть описан тот же текст, что содержится в ней.
 
  
 
:Данный язык не является регулярным, однако его можно представить с помощью регулярных выражений с использованием обратных ссылок.
 
:Данный язык не является регулярным, однако его можно представить с помощью регулярных выражений с использованием обратных ссылок.
Строка 26: Строка 24:
 
* Запишем регулярное выражение для языка <tex>L=b^kab^kab^ka</tex>. Данный язык не является ни регулярным, ни контекстно-свободным (по [[Лемма о разрастании для КС-грамматик|лемме о разрастании]]), но также легко представим с помощью обратных ссылок:
 
* Запишем регулярное выражение для языка <tex>L=b^kab^kab^ka</tex>. Данный язык не является ни регулярным, ни контекстно-свободным (по [[Лемма о разрастании для КС-грамматик|лемме о разрастании]]), но также легко представим с помощью обратных ссылок:
  
:<tex>L=(b\{b\}^*a)\backslash 1\backslash 1</tex>
+
:<tex>L=(b\{b\}^*a)\backslash 1\backslash 1</tex>.
 +
 
 +
:Группа <tex>1</tex> {{---}} <tex>(b\{b\}^∗a)</tex> {{---}} представляет из себя регулярное выражение для языка <tex>L=b^ka,k>0\,</tex>, последующие за ней обратные ссылки используются для многократного использования ''текста'' группы. Поэтому после «<tex>b^ka</tex>» обязан присутствовать текст «<tex>b^kab^ka</tex>».
  
 
* Язык <tex>L=a^nb^n,\,n>0\,</tex> можно представить при помощи обратных ссылок:
 
* Язык <tex>L=a^nb^n,\,n>0\,</tex> можно представить при помощи обратных ссылок:
Строка 33: Строка 33:
  
 
:где «<tex>?1</tex>» – ссылка, осуществляющая рекурсивный вызов первой группы. Следущий за ссылкой знак вопроса обозначает использование группы <tex>0</tex> или <tex>1</tex> раз, то есть осуществление рекурсивного вызова или его окончание.
 
:где «<tex>?1</tex>» – ссылка, осуществляющая рекурсивный вызов первой группы. Следущий за ссылкой знак вопроса обозначает использование группы <tex>0</tex> или <tex>1</tex> раз, то есть осуществление рекурсивного вызова или его окончание.
 +
 +
:<tex>?1</tex> ссылается на первую группу {{---}}
 <tex>(a(?1)?b)</tex>, что равносильно рекурсивной зависимости:
       
 +
::::<tex>(a(?1)?b)=</tex>

 +
:::<tex>=(a(a(?1)?b)?b)=</tex>
 +
::<tex>=(a(a(a(?1)?b)?b)?b)=</tex>
 +
:<tex>=(a(a(a(a(?1)?b)?b)?b)?b)=\cdots</tex>
 +
 +
:Очевидно, что все слова из языка <tex>L</tex> удовлетворяют данному регулярному выражению.
  
 
==Теорема о КС-языках==
 
==Теорема о КС-языках==
Строка 39: Строка 47:
 
|statement=С помощью механизма обратных ссылок можно представить любой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободный язык]].
 
|statement=С помощью механизма обратных ссылок можно представить любой [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора|контекстно-свободный язык]].
 
|proof=
 
|proof=
По определению контекстно-свободного языка, любой КС-язык реализуется с помощью продукций нескольких видов; для каждого из них покажем, что его можно реализовать с использованием регулярных выражений с обратными ссылками.
+
Любую контекстно-свободную грамматику можно привести к [[Нормальная форма Хомского|нормальной форме Хомского]], следовательно, достаточно доказать, что грамматику, заданную в нормальной форме, можно преобразовать в регулярное выражение с обратными ссылками. 
Рассмотрим правила, которые могут содержаться в такой грамматике:

  
Рассмотрим один из таких:
+
<tex>A\rightarrow BC</tex>
 +
 
 +
<tex>
A\rightarrow a</tex>
 +
 
 +
<tex>
S\rightarrow\varepsilon</tex>
 +
 
 +


Представим каждое из них в виде регулярного выражения с обратными ссылками.
 +
 
 +

Используя ссылки на регулярные выражения, соответствующие нетерминалам <tex>B</tex> и <tex>C</tex>, можно представить первое правило:

 +
 
 +
<tex>A\rightarrow BC\leftrightarrow A=((?B)\,(?C)).\,</tex> 

 +
 
 +
Второе и третье правила не требуют использования обратных ссылок:
 +
 
 +

<tex>A\rightarrow a\leftrightarrow A=a;</tex>
 +
 
 +

<tex>S\rightarrow\varepsilon\leftrightarrow S=\varepsilon.</tex>
 +
 
 +
Таким образом, регулярные выражения с обратными ссылками имеют бо́льшую мощность по сравнению с обычными. С их помощью реализуются как регулярные языки, так и контекстно-свободные грамматики, а также некоторые [[Иерархия Хомского формальных грамматик|контекстно-зависимые]].
 +
}}
 +
 
 +
 
 +
Рассмотрим следующую КС-грамматику:
  
 
<tex>S\rightarrow A\\A\rightarrow BC\\A\rightarrow CD</tex>
 
<tex>S\rightarrow A\\A\rightarrow BC\\A\rightarrow CD</tex>
Строка 47: Строка 77:
 
Очевидно, что эквивалентным будет выражение <tex>((?B)\,(?C)\,|\,(?C)\,(?D))\,</tex>, где <tex>B, C, D</tex> {{---}} группы.
 
Очевидно, что эквивалентным будет выражение <tex>((?B)\,(?C)\,|\,(?C)\,(?D))\,</tex>, где <tex>B, C, D</tex> {{---}} группы.
  
Аналогично с КС-языком, одна из продукций которого представлена в виде <tex>A\rightarrow A...,\,</tex> например, регулярное выражение для языка:
 
  
<tex>S\rightarrow A\\A\rightarrow \varepsilon\\A\rightarrow BA\\B\rightarrow b\\B\rightarrow c</tex>
+
Другой пример:
  
будет выглядеть так: <tex>((b\,|\,c)\,(?1)?).</tex>
+
<tex>S\rightarrow A\\A\rightarrow\varepsilon\\A\rightarrow BA\\B\rightarrow b\\B\rightarrow c</tex>
  
То есть правила вида <tex>A\rightarrow BCD...\,</tex> реализуются при помощи ссылок на соответствующие группы, а для правил вида <tex>A\rightarrow A...\,</tex> используется обратная ссылка на ту же самую группу, для которой создаётся правило. При наличии нескольких правил в регулярном выражении пишется логическое «или».
+
Регулярное выражение для этой грамматики будет выглядеть так: <tex>((b\,|\,c)\,(?1)?).</tex>
 
+
==Применение==
Таким образом, регулярные выражения с обратными ссылками имеют бо́льшую мощность по сравнению с обычными. С их помощью реализуются как регулярные языки, так и контекстно-свободные, а также некоторые [[Иерархия Хомского формальных грамматик|контестно-зависимые]].
+
С помощью обратных ссылок можно составить регулярные выражения для языка тандемных повторов и других языков, где требуется «запоминать» части входящих в язык слов.
}}
 
  
 +
Регулярные выражения в языках программирования зачастую поддерживают обратные ссылки. На практике их можно использовать, например, для парсинга html-выражений (поиск подстрок, содержащихся в определённых тегах).
 
==См. также==
 
==См. также==
 
* [[Регулярные языки: два определения и их эквивалентность]]
 
* [[Регулярные языки: два определения и их эквивалентность]]
 
* [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора]]
 
* [[Контекстно-свободные грамматики, вывод, лево- и правосторонний вывод, дерево разбора]]
 +
* [[Нормальная форма Хомского]]
 
* [[Иерархия Хомского формальных грамматик]]
 
* [[Иерархия Хомского формальных грамматик]]
  

Версия 20:52, 13 мая 2018

Определение:
Регулярные выражения с обратными ссылками (англ. regex with backreferences) — одна из разновидностей регулярных выражений, дающая возможность использовать в них слова, принадлежащие некоторой группе.

[math](aba)c\backslash 1[/math] — пример такого регулярного выражения.

Выражение, заключённое в скобки, называется группой (англ. capture group). Скобки захватывают текст, сопоставленный регулярным выражением внутри нумерованной группы, который может быть повторно использован с помощью обратной ссылки с указанием номера группы.

«[math]\backslash[/math]» – символ обратной ссылки (англ. backreference), который действует на первую группу. Обратная ссылка [math]\backslash 1[/math] показывает, что после группы [math]1[/math][math](aba)[/math] — и символа [math]c[/math] должен быть описан тот же текст, что содержится в ней.

Порядок нумерации групп: сначала внешняя, потом вложенные (в порядке обхода в глубину).

Примеры

[math]L=((0|1)^∗)\backslash 1[/math]
Данный язык не является регулярным, однако его можно представить с помощью регулярных выражений с использованием обратных ссылок.
  • Выведем регулярное выражение для языка, состоящего из палиндромов фиксированной длины [math]n=2\cdot m\,[/math] или [math]\,n=2\cdot m+1[/math]:
  1. для чётного [math]n[/math]: [math]\;(.)(.)(.)...(.)\backslash m...\backslash 3\backslash 2\backslash 1;[/math]
  2. для нечётного [math]n[/math]: [math]\;(.)(.)(.)...(.).\backslash m...\backslash 3\backslash 2\backslash 1,\;[/math]
где «[math].[/math]» – любой одиночный символ.
  • Запишем регулярное выражение для языка [math]L=b^kab^kab^ka[/math]. Данный язык не является ни регулярным, ни контекстно-свободным (по лемме о разрастании), но также легко представим с помощью обратных ссылок:
[math]L=(b\{b\}^*a)\backslash 1\backslash 1[/math].
Группа [math]1[/math][math](b\{b\}^∗a)[/math] — представляет из себя регулярное выражение для языка [math]L=b^ka,k\gt 0\,[/math], последующие за ней обратные ссылки используются для многократного использования текста группы. Поэтому после «[math]b^ka[/math]» обязан присутствовать текст «[math]b^kab^ka[/math]».
  • Язык [math]L=a^nb^n,\,n\gt 0\,[/math] можно представить при помощи обратных ссылок:
[math]L=(a(?1)?b),[/math]
где «[math]?1[/math]» – ссылка, осуществляющая рекурсивный вызов первой группы. Следущий за ссылкой знак вопроса обозначает использование группы [math]0[/math] или [math]1[/math] раз, то есть осуществление рекурсивного вызова или его окончание.
[math]?1[/math] ссылается на первую группу —
 [math](a(?1)?b)[/math], что равносильно рекурсивной зависимости:

[math](a(?1)?b)=[/math]
[math]=(a(a(?1)?b)?b)=[/math]
[math]=(a(a(a(?1)?b)?b)?b)=[/math]
[math]=(a(a(a(a(?1)?b)?b)?b)?b)=\cdots[/math]
Очевидно, что все слова из языка [math]L[/math] удовлетворяют данному регулярному выражению.

Теорема о КС-языках

Теорема:
С помощью механизма обратных ссылок можно представить любой контекстно-свободный язык.
Доказательство:
[math]\triangleright[/math]

Любую контекстно-свободную грамматику можно привести к нормальной форме Хомского, следовательно, достаточно доказать, что грамматику, заданную в нормальной форме, можно преобразовать в регулярное выражение с обратными ссылками. 
Рассмотрим правила, которые могут содержаться в такой грамматике:


[math]A\rightarrow BC[/math]

[math]
A\rightarrow a[/math]

[math]
S\rightarrow\varepsilon[/math]



Представим каждое из них в виде регулярного выражения с обратными ссылками.


Используя ссылки на регулярные выражения, соответствующие нетерминалам [math]B[/math] и [math]C[/math], можно представить первое правило:


[math]A\rightarrow BC\leftrightarrow A=((?B)\,(?C)).\,[/math]

Второе и третье правила не требуют использования обратных ссылок:

[math]A\rightarrow a\leftrightarrow A=a;[/math]

[math]S\rightarrow\varepsilon\leftrightarrow S=\varepsilon.[/math]

Таким образом, регулярные выражения с обратными ссылками имеют бо́льшую мощность по сравнению с обычными. С их помощью реализуются как регулярные языки, так и контекстно-свободные грамматики, а также некоторые контекстно-зависимые.
[math]\triangleleft[/math]


Рассмотрим следующую КС-грамматику:

[math]S\rightarrow A\\A\rightarrow BC\\A\rightarrow CD[/math]

Очевидно, что эквивалентным будет выражение [math]((?B)\,(?C)\,|\,(?C)\,(?D))\,[/math], где [math]B, C, D[/math] — группы.


Другой пример:

[math]S\rightarrow A\\A\rightarrow\varepsilon\\A\rightarrow BA\\B\rightarrow b\\B\rightarrow c[/math]

Регулярное выражение для этой грамматики будет выглядеть так: [math]((b\,|\,c)\,(?1)?).[/math]

Применение

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

Регулярные выражения в языках программирования зачастую поддерживают обратные ссылки. На практике их можно использовать, например, для парсинга html-выражений (поиск подстрок, содержащихся в определённых тегах).

См. также

Источники информации