Грамматика регулярных выражений включает специальные символы определе_ ния альтернатив, подвыражений группировки и ссылок на предыдущие подвы_ ражения. Символ вертикальной черты | служит для разделения альтернатив. Например, /ab|cd|ef/ соответствует либо строке «ab», либо строке «cd», либо строке «ef», а шаблон /\d{3}|[a_z]{4}/ – либо трем цифрам, либо четырем строч_ ным буквам.
Обратите внимание: альтернативы обрабатываются слева направо до тех пор, по_ ка не будет найдено соответствие. Если левая альтернатива найдена, правая иг_ норируется, даже если может добиться «лучшего» соответствия. Поэтому когда к строке «ab» применяется шаблон /a|ab/, он будет соответствовать только пер_ вому символу.
Круглые скобки имеют в регулярных выражениях несколько значений. Одно из них – группировка отдельных элементов в одно подвыражение, так что элементы при использовании спецсимволов |, *, +, ? и прочих спецсимволов рассматрива_ ются как одно целое. Например, /java(script)?/ соответствует слову «java», за ко_ торым следует необязательное слово «script», а /(ab|cd)+|ef)/ соответствует либо строке «ef», либо одному или более повторений одной из строк «ab» или «cd».
Другим применением скобок в регулярных выражениях является определение подшаблонов внутри шаблона. Когда в целевой строке найдено соответствие ре_
220 Глава 11. Шаблоны и регулярные выражения
гулярному выражению, можно извлечь часть целевой строки, соответствующую любому конкретному подшаблону, заключенному в скобки. (Мы увидим, как по_ лучить эти подстроки, позднее в этой главе.) Предположим, что требуется оты_ скать одну или более букв в нижнем регистре, за которыми следует одна или не_ сколько цифр. Для этого можно воспользоваться шаблоном /[a_z]+\d+/. Но пред_ положим также, что нам нужны только цифры в конце каждого соответствия. Если мы поместим эту часть шаблона в круглые скобки (/[a_z]+(\d+)/), то смо_ жем извлечь цифры из любых найденных нами соответствий. Позднее я объяс_ ню, как это делается.
С этим связано еще одно применение подвыражений в скобках, позволяющее де_ лать ссылку назад к подвыражению из предыдущей части того же регулярного выражения. Это достигается путем указания одной или нескольких цифр после символа \. Цифры ссылаются на позицию подвыражения в скобках внутри регу_ лярного выражения. Например, \1 ссылается на первое подвыражение, а \3 – на третье. Обратите внимание: поскольку подвыражения могут быть вложены одно в другое, при подсчете используется позиция левой скобки. Например, в следую_ щем регулярном выражении ссылка на вложенное подвыражение ([Ss]cript) бу_ дет выглядеть как \2:
/([Jj]ava([Ss]cript)?)\sis\s(fun\w*)/
Ссылка на подвыражение регулярного выражения указывает не на шаблон этого подвыражения, а на найденный текст, соответствующий этому шаблону. Поэто_ му ссылки могут использоваться для наложения ограничения, выбирающего части строки, содержащие точно такие же символы. Например, следующее регу_ лярное выражение соответствует нулю или более символам внутри одинарных или двойных кавычек. Однако оно не требует, чтобы открывающие и закрываю_ щие кавычки соответствовали друг другу (т. е. чтобы обе кавычки были одинар_ ными или двойными):
/['"][^'"]*['"]/
Соответствия кавычек мы можем потребовать посредством такой ссылки:
/(['"])[^'"]*\1/
Здесь \1 соответствует результату поиска в соответствии с первым подвыражени_ ем. В этом примере ссылка налагает ограничение, требующее, чтобы закрываю_ щая кавычка соответствовала открывающей. Это регулярное выражение не до_ пускает присутствия одинарных кавычек внутри двойных, и наоборот. Недопус_ тимо помещать ссылки внутрь классов символов, т. е. мы не можем написать:
/(['"])[^\1]*\1/
Позднее в этой главе мы увидим, что этот вид ссылок на подвыражения представ_ ляет собой мощное средство для использования регулярных выражений в опера_ циях поиска/замены.
В JavaScript 1.5 (но не в JavaScript 1.2) возможна группировка элементов в регу_ лярном выражении без создания нумерованной ссылки на эти элементы. Вместо простой группировки элементов между ( и ) начните группу с символов (?: и за_ кончите ее символом ). Рассмотрим, например, следующий шаблон:
/([Jj]ava(?:[Ss]cript)?)\sis\s(fun\w*)/
11.1. Определение регулярных выражений
Здесь подвыражение (?:[Ss]cript) нужно только для группировки, чтобы к груп_ пе мог быть применен символ повторения ?. Эти модифицированные скобки не создают ссылку, поэтому в данном регулярном выражении \2 ссылается на текст, соответствующий шаблону (fun\w*).
В табл. 11.4 приводится перечень операторов альтернативы, группировки и ссыл_ ки в регулярных выражениях.
Таблица 11.4. Символы альтернативы, группировки и ссылки в регулярных выражениях