Wiki-учебник по веб-технологиям: JavaScript/РегулярныеВыражения ...

Главная | Каталог |

Регулярные выражения


Оглавление документа


Регулярные выражения являются патэрнами, используемыми при поиске совпадений комбинаций символов в строках. В JavaScript регулярные выражения являются также объектами. Эти патэрны используются вместе с методами exec и test объекта **RegExp** и с методами match, replace, search и split объекта String.
В этой главе рассматриваются регулярные выражения JavaScript.


JavaScript 1.1 и ранее.

Регулярные выражения недоступны в JavaScript 1.1 и более ранних версиях.

В этой главе имеются следующие разделы:





1. Создание регулярного выражения


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


re = /ab+c/
Литералы регулярного выражения дают возможность компилировать регулярное выражение при вычислении скрипта. Когда регулярное выражение остаётся постоянным, используёте этот способ для повышения производительности.


re = new RegExp("ab+c")
Использование конструктора функции даёт возможность компилировать регулярное выражение на этапе прогона программы. Используйте конструктор функции, если Вам известно, что патэрн регулярного выражения будет изменяться или если Вы не знаете патэрн и получаете его из другого источника, такого как пользовательский ввод.

2. Написание патэрна регулярного выражения


Патэрн регулярного выражения состоит из обычных символов, таких как /abc/ или из комбинаций обычных и специальных символов, таких как /ab*c/ или /Chapter (\d+)\.\d*/. В последнем примере есть скобки, которые используются в качестве запоминающего устройства. Совпадение этой части патэрна запоминается для последующего использования, как описано в разделе «Использование Совпадений Подстрок в Скобках».

2.1. Использование простых патэрнов


Простые патэрны составляются из символов, для которых Вы ищете прямое совпадение. Например, патэрн /abc/ совпадает в строке только с точными комбинациями указанных символов 'abc' в указанном порядке. Такое совпадение произойдёт в строках “Hi, do you know your abc's?” и “The latest airplane designs evolved from slabcraft.” В обоих случаях совпадение произойдёт с подстрокой 'abc'. В строке “Grab crab” совпадения не будет, поскольку она не содержит подстроки 'abc'.

2.2. Использование специальных символов


Если при поиске требуется нечто большее, чем простое совпадение, например, найти один или более символов b или найти пробел, в патэрн включаются специальные символы. Например, патэрн /ab*c/ совпадает с любой комбинацией символов, в которой после одиночной 'a' идёт нуль или более символов 'b» (* означает 0 или более вхождений предшествующего элемента/символа) и сразу за ними – 'c'. В строке “cbbabbbbcdebc” этот патэрн совпадёт с подстрокой 'abbbbc'.

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

Таблица 4.1 Специальные символы в регулярных выражениях
СимволЗначение
\
Одно из следующих:

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

Например, /b/ совпадает с символом 'b'. Поместив backslash перед b, то есть так: /\b/, мы делаем символ специальным, в данном случае – означающим границу слова.

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

Например, * это специальный символ, означающий 0 или более вхождений предыдущего символа; например, /a*/ означает 0 или более 'a'. Чтобы подставит * литерально, ставим перед ним backslash; например, /a\*/ совпадает с 'a*'.
^
Соответствует началу ввода. Если многострочный флаг установлен в true, совпадает также сразу после символа разрыва строки.

Например, /^A/ не совпадает с 'A' в строке “an A”, но совпадает с первым 'A' в строке “An A”.
$Совпадает с концом ввода. Если многострочный флаг установлен в true, совпадает также непосредственно перед символом разрыва строки.

Например, /t$/ не совпадает с 't' в строке “eater”, но совпадает с в строке “eat”.
*Предшествующий символ совпадает 0 или более раз.

Например, /bo*/ совпадает с 'boooo' в строке “A ghost booooed” и с 'b' в “A bird warbled”, но не совпадает ни с чем в строке “A goat grunted”.
+Предшествующий символ совпадает 1 или более раз. Эквивалентно {1,}.

Например, /a+/ совпадает с 'a' в “candy” и со всеми 'a' в “caaaaaaandy”.
?Предшествующий символ совпадает 0 или 1 раз.

Например, /e?le?/ совпадает с 'el' в “angel” и с 'le' в “angle.”

Если используется сразу после квантификаторов *, +, ? или {}, делает квантификатор нежадным (совпадает минимальное число раз), что противоположно действию по умолчанию, когда квантификатор – жадный (совпадает максимальное число раз).

Используется также во вперёдсмотрящих/lookahead утверждениях, описанных в пунктах о x(?=y) и x(?!y) в этой таблице.
.(Десятичная точка) совпадает с любым одиночным символом, исключая символ новой строки.

Например, /.n/ совпадает с 'an' и с 'on' в “nay, an apple is on the tree”, но не с 'nay'.
(x)Совпадает с 'x' и запоминает совпадение. Это называется «захватывающие скобки».

Например, /(foo)/ совпадает с 'foo', и запоминает её, в “foo bar.” Совпадающая подстрока может быть вызвана из элементов результирующего массива [1], ..., [n].
(?:x)Совпадает с 'x', но не запоминает совпадение. Это называется «незахватывающие скобки». Совпадающая подстрока не может быть вызвана из элементов результирующего массива [1], ..., [n].
x(?=y)Совпадает с 'x' только в том случае, если после 'x' следует 'y'. Например, /Jack(?=Sprat)/ совпадает с 'Jack' только тогда, когда следом идёт 'Sprat'. /Jack(?=Sprat|Frost)/ совпадает с 'Jack' только тогда, когда следом идёт 'Sprat' или 'Frost'. Однако ни 'Sprat', ни 'Frost' не являются частью результата совпадения.
x(?!y)Совпадает с 'x' только в том случае, если после 'x' не следует 'y'. Например, /\d+(?!\.)/ совпадает с числом только в том, случае, если после него нет десятичной точки. регулярное выражение /\d+(?!\.)/.exec(«3.141») совпадает с 141, но не совпадает с 3.141.
x|yСовпадает с 'x' или 'y'.

Например, /green|red/ совпадает с 'green' в “green apple” и с 'red' в “red apple.”
{n} Где n это положительное целое. Совпадает с точно n-количеством вхождений предшествующего символа.

Например, /a{2}/ не совпадает с 'a' в “candy,” но совпадает со всеми 'a' в “caandy” и с первыми двумя 'a's в “caaandy.”
{n,}Где n это положительное целое. Совпадает с как минимум n вхождений предшествующего символа.

Например, /a{2,} не совпадает с 'a' в “candy”, но совпадает со всеми 'a' в “caandy” и в “caaaaaaandy.”
{n,m}Где n и m это положительные целые. Совпадает с минимум n и с максимум m вхождений предшествующего символа.

Например, /a{1,3}/ не совпадает ни с чем в “cndy”, совпадает с 'a' в “candy”, с первыми двумя 'a' в “caandy” и с первыми тремя 'a' в “caaaaaaandy” Заметьте, что при совпадении с “caaaaaaandy”, совпадёт “aaa”, хотя оригинальная строка содержит большее количество 'a'.
[xyz]Набор символов. Совпадение с одним из символов в скобках. Можно специфицировать диапазон символов с помощью дефиса.

Например, [abcd] это то же самое, что и [a-d]. Совпадает с 'b' в “brisket” и с 'c' в “ache”.
[^xyz]Отрицание предложенного набора символов. То есть совпадает со всем, кроме того, что заключено в скобки. Можно специфицировать диапазон символов с помощью дефиса.

Например, [^abc] это то же самое, что [^a-c]. Они совпадают с 'r' в “brisket” и с 'h' в “chop.”
[\b]Совпадает с backspace (не путайте с \b).
\bСовпадает на границе слова с таким символом, как space и символ новой строки (не путайте с[\b]).

Например, /\bn\w/ совпадает с 'no' в “noonday”; /\wy\b/ совпадает с 'ly' в “possibly yesterday.”
\BСовпадает не на границе слова.

Например, /\w\Bn/ совпадает с 'on' в “noonday”, а /y\B\w/ совпадает с 'ye' в “possibly yesterday.”
\cXГде X это управляющий символ. Совпадает с управляющим символом.

Например, /\cM/ совпадает с control-M в строке.
\dСовпадает с цифровым символом. Эквивалентно [0–9].

Например, /\d/ или /[0–9]/ совпадает с '2' в “B2 is the suite number.”
\DСовпадает с любым нецифровым символом. Эквивалентно [^0–9].

Например, /\D/ или /[^0–9]/ совпадает с 'B' в “B2 is the suite number.”
\fСовпадает с символом прогона страницы/form-feed.
\nСовпадает с символом прогона строки/linefeed.
\rСовпадает с символом возврата каретки/carriage return.
\sСовпадает с одиночным пробельным символом, включая space, tab, form feed, line feed. Эквивалентно [ \f\n\r\t\v\u00A0\u2028\u2029].

Например, /\s\w*/ совпадает с ' bar' в “foo bar.”
\SСовпадает с одиночным символом, отличным от пробельного символа. Эквивалентно [ ^\f\n\r\t\v\u00A0\u2028\u2029].

Например, /\S\w*/ совпадает с 'foo' в “foo bar.”
\tСовпадает с табуляцией/tab.
\vСовпадает с вертикальной табуляцией/vertical tab.
\wСовпадает с любым алфавитным символом, включая символ подчёркивания/underscore. Эквивалентно [A-Za-z0–9_].

Например, /\w/ совпадает с 'a' в “apple,” с '5' в "$5.28” и с '3' в “3D.”
\WСовпадает с любым несловарным символом. Эквивалентно [^A-Za-z0–9_].

Например, /\W/ или /[^$A-Za-z0–9_]/ совпадает с '%' в «50%.»
\nГде n это положительное целое. Обратная ссылка на последнюю подстроку, совпавшую с n вхождений символа в скобках в регулярном выражении (включая левые скобки). (Здесь не совсем чётко... Прим. перев.)

Например, /apple(,)\sorange\1/ совпадает с 'apple, orange,' в “apple, orange, cherry, peach.”
\0Совпадает с символом NUL. Не вводите после него других цифр.
\xhhСовпадает с символом с 16-ричным кодом hh (две 16-ричные цифры)
\uhhhhСовпадает с символом с 16-ричным кодом hhhh (четыре 16-ричные цифры).

2.3. Использование скобок


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

Например, патэрн /Chapter (\d+)\.\d*/ иллюстрирует использование дополнительных escape-ированных и специальных символов и указывает, что эта часть патэрна должна быть запомнена. Он совпадает точно с символами 'Chapter ' с последующими одним или более цифровыми символами (\d означает любой цифровой символ, а + означает 1 или более раз), с последующей десятичной точкой (которая сама по себе является специальным символом; предварение десятичной точки символом \ означает, что патэрн обязан искать специальный литеральный символ '.'), с последующим любым цифровым символом 0 или более раз(\d означает цифровой символ, * означает 0 или более раз). Кроме того, используются скобки для запоминания первых совпавших цифровых символов.

Этот патэрн будет найден в строке «Open Chapter 4.3, paragraph 6", и '4' будет запомнена. Патэрн не будет найден в строке «Chapter 3 and 4", поскольку здесь отсутствует десятичная точка после цифры '3'.

Чтобы найти совпадение с подстрокой без запоминания совпавшей части, предваряйте патэрн внутри скобок символами ?:. Например, (?:\d+) совпадает с единицей или числовым символом, но не запоминает совпавшие символы.

3. Работа с регулярными выражениями


Регулярные выражения используются с методами test и exec объекта **RegExp** и с методами match, replace, search и split объекта String.Эти методы рассматриваются в книге Ядро JavaScript. Справочник.

Таблица 4.2 Методы, Использующие Регулярные Выражения.
МетодОписание
execМетод объекта RegExp, выполняющий поиск совпадения в строке. Возвращает массив информации.
testМетод объекта RegExp, тестирующий на совпадение в строке. Возвращает true или false.
matchМетод объекта String, выполняющий поиск совпадения в строке. Возвращает массив информации или null при отсутствии совпадений.
searchМетод объекта String, тестирующий на совпадение в строке. Возвращает индекс совпадения или -1, если поиск завершился ничем.
replaceМетод объекта String, выполняющий поиск совпадения в строке и замещающий совпавшую подстроку замещающей подстрокой.
splitМетод объекта String, использующий регулярное выражение или фиксированную строку для разбивки строки на массив подстрок.

Если Вам нужно знать, найден ли патэрн в строке, используйте методы test или search; для получения большей информации (но при замедлении выполнения) используйте методы exec или match. Если Вы используете методы exec или match и если совпадение найдено, эти методы возвращают массив и обновляют свойства объекта регулярного выражения, а также предопределённого объекта регулярного выражения, RegExp. Если совпадение не найдено, метод exec возвращает null (которое конвертируется в false).

В следующем примере скрипт использует метод exec для поиска совпадения в строке:

<SCRIPT LANGUAGE="JavaScript1.2">
myRe=/d(b+)d/g;
myArray = myRe.exec("cdbbdbsbz");
</SCRIPT>


Если Вам не нужен доступ к свойствам регулярного выражения, альтернативным способом создания myArray будет такой скрипт:

<SCRIPT LANGUAGE="JavaScript1.2">
myArray = /d(b+)d/g.exec("cdbbdbsbz");
</SCRIPT>


Если Вы хотите сконструировать регулярное выражение из строки, вот ещё один скрипт:

Highlighter for JAVSCRIPT not found

С помощью этих скриптов находится совпадение и возвращается массив и обновляются свойства, показанные в следующей таблице.

Таблица 4.3 Результаты Выполнения Регулярного Выражения.
ОбъектСвойство или ИндексОписаниеВ этом примере:
myArrayindexИндекс совпадений во вводе с базой 0.1
inputСтрока-оригинал.“cdbbdbsbz”
[0]Последние совпавшие символы.“dbbd”
myRelastIndexИндекс, начиная с которого стартует следующее совпадение. (Это свойство установлено только тогда, когда регулярное выражение использует опцию g, описанную в разделе Выполнение Глобального Поиска, Игнорирование Регистра и Рассмотрение Многострочного Ввода.)5
sourceТекст патэрна. Обновляется в момент создания регулярного выражения, не исполняется.«d(b+)d»

Как показано во второй форме этого примера, Вы можете использовать регулярное выражение, созданное с помощью инициализатора объекта, без присвоения его переменной. Если Вы всё же это сделаете, каждое вхождение будет новым регулярным выражением. Исходя из этого, если Вы используете форму без присвоения выражения переменной, Вы не сможете затем получить доступ к свойствам этого регулярного выражения. Например, у Вас есть скрипт:

<SCRIPT LANGUAGE="JavaScript1.2">
myRe=/d(b+)d/g;
myArray = myRe.exec("cdbbdbsbz");
document.writeln("The value of lastIndex is " + myRe.lastIndex);
</SCRIPT>


Вывод этого скрипта:

The value of lastIndex is 5

Если Ваш скрипт, однако, будет таким:

<SCRIPT LANGUAGE="JavaScript1.2">
myArray = /d(b+)d/g.exec("cdbbdbsbz");
document.writeln("The value of lastIndex is " + /d(b+)d/g.lastIndex);
</SCRIPT>


он выдаст:

The value of lastIndex is 0

Вхождения /d(b+)d/g в этих двух операторах являются разными объектами регулярного выражения и, соответственно, имеют разные значения свойства lastIndex. Если Вам нужен доступ к свойствам регулярного выражения, созданного с помощью инициализатора объекта, Вы должны сначала присвоить это выражение переменной.

3.1. Использование совпадений подстрок в скобках


Включение скобок в патэрн регулярного выражения вызывает запоминание соответствующего подсовпадения. Например, /a(b)c/ совпадает с символами 'abc' и запоминает 'b'. Чтобы вызвать эту подстроку в скобках, используйте Array-элементы [1], ..., [n].

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

Пример 1.

В этом скрипте используется метод replace для изменения-переключения слов в строке. Для замещающего текста в скрипте используется $1 и $2 для обозначения первой строки и второй подстроки в скобках.

<SCRIPT LANGUAGE="JavaScript1.2">
re = /(\w+)\s(\w+)/;
str = "John Smith";
newstr = str.replace(re, "$2, $1");
document.write(newstr)
</SCRIPT>


Будет напечатано “Smith, John”.

Пример 2.

Здесь RegExp.input устанавливается событием Change. В функции getInfo метод exec, вызываемый с использованием сокращённой нотации (), использует значение RegExp.input в качестве аргумента.

<HTML>

<SCRIPT LANGUAGE="JavaScript1.2">
function getInfo(){
   a = /(\w+)\s(\d+)/();
   window.alert(a[1] + ", your age is " + a[2]);
}
</SCRIPT>

Enter your first name and your age, and then press Enter.

<FORM>
<INPUT TYPE="text" NAME="NameAge" onChange="getInfo(this);">
</FORM>

</HTML>



3.2. Выполнение глобального поиска, игнорирование регистра и рассмотрение многострочного ввода


Регулярные выражения могут иметь три опции-флага, дающие возможность выполнять глобальный и нечувствительный к регистру поиск. Для глобального поиска используйте флаг g. Для поиска без учёта регистра используйте флаг i. Для многострочного поиска – флаг m. Эти флаги могут использоваться независимо или вместе в любом порядке и являются частью регулярного выражения.

Для включения флага используется следующий синтаксис:

re = /pattern/flags
re = new RegExp("pattern", ["flags"])

Обратите внимание, что флаги интегрированы в регулярное выражение. Они не могут быть позднее добавлены или удалены.

Например, re = /\w+\s/g создаёт регулярное выражение, которое ищет один или более символов с последующим пробелом по всей строке.

Formatter «highlight/рд» not found

Отобразится ["fee “, «fi “, “fo "]. В этом примере Вы можете заменить строку:

re = /\w+\s/g;

на строку:

re = new RegExp("~\\w+~\\s", “g”);

и получить аналогичный результат.

Флаг m используется flag для специфицирования того, что многострочный ввод должен рассматриваться как несколько строк. Если используется флаг m, то ^ и $ совпадают в начале и в конце любой строки общей строки ввода, вместо начала и конца всей строки ввода.

4. Примеры


Несколько примеров использования регулярных выражений.

4.1. Изменение порядка в строке ввода


В этом примере показано форматирование регулярного выражения и использование методов string.split() и string.replace(). Очищается необработанная строка ввода, содержащая имена (сначала имя, потом фамилия), разделённые пробелами, табуляцией и одиночным символом «точка с запятой». Наконец, имена и фамилии меняются местами (сначала – фамилия) и список сортируется.

<SCRIPT LANGUAGE="JavaScript1.2">
 
// Строка names содержит несколько пробелов и табуляций,
// и может содержать несколько пробелов между первым и последним именем.
names = new String ( "Harry Trump ;Fred Barney; Helen Rigby ;\
       Bill Abel ;Chris Hand ")
 
document.write ("---------- Original String" + "<BR>" + "<BR>");
document.write (names + "<BR>" + "<BR>");
 
// Подготавливаются два патэрна регулярных выражения и массив для хранения.
// Строка делится на элементы массива.
 
// pattern: возможен пробел, затем точка с запятой, затем пустое пространство
pattern = /\s*;\s*/;
 
// Строка разбивается на куски, разделённые патэрном, и
// эти куски сохраняются в массиве nameList
nameList = names.split (pattern);
 
// Новый pattern: один или более символов, затем пробелы, затем символы.
// Используются скобки для "запоминания" части патэрна.
// Запомненная часть будет использоваться позднее.
pattern = /(\w+)\s+(\w+)/;
 
// Новый массив для содержания имён.
bySurnameList = new Array;
 
// Выводит массив имён и заполняет новый массив
// именами, разделёнными запятыми, сначала - фамилия.
//
// Метод replace удаляет любое совпадение с патэрном
// и замещает его запомненной строкой - второй запомненной частью,
// после которой идёт запятая, пробел и первая запомненная часть.
//
// Переменные $1 и $2 ссылаются на части,
// запомненные при совпадении патэрна.
 
document.write ("---------- After Split by Regular Expression" + "<BR>");
for ( i = 0; i < nameList.length; i++) {
   document.write (nameList[i] + "<BR>");
   bySurnameList[i] = nameList[i].replace (pattern, "$2, $1")
}
 
// Отображается новый массив.
document.write ("---------- Names Reversed" + "<BR>");
for ( i = 0; i < bySurnameList.length; i++) {
   document.write (bySurnameList[i] + "<BR>")
}
 
// Сортируется по фамилии, затем выводится отсортированный массив.
bySurnameList.sort();
document.write ("---------- Sorted" + "<BR>");
for ( i = 0; i < bySurnameList.length; i++) {
   document.write (bySurnameList[i] + "<BR>")
}
 
document.write ("---------- End" + "<BR>")
 
</SCRIPT>


4.2. Использование специальных символов для проверки ввода


В этом примере пользователь вводит телефонный номер. Когда нажимается Enter, скрипт проверяет правильность ведённого номера. Если номер введён правильно (соответствует последовательности символов, специфицированной регулярным выражением), скрипт выводит окно с подтверждением и благодарностью. Если номер введён неправильно, скрипт выводит окно, информирующее пользователя, что номер введён неправильно.

Регулярное выражение ищет 0 или более открывающих скобок \(? с последующими тремя цифрами \d{3}, с последующими 0 или более закрывающими скобками \)?, с последующим тире, слэшем или или десятичной точкой и, если найдёт, запоминает символ ([-\/\.]), последующие три цифры \d{3}, тире, слэш или десятичную точку \1, с последующими 4 цифрами\d{4}.

Событие Change активируется, когда пользователь нажимает Enter, и устанавливает значение RegExp.input.

<HTML>
<SCRIPT LANGUAGE = "JavaScript1.2">

re = /\(?\d{3}\)?([-\/\.])\d{3}\1\d{4}/;

function testInfo() {
   OK = re.exec();
   if (!OK)
      window.alert (~RegExp.input +
         " isn't a phone number with area code!")
   else
      window.alert ("Thanks, your phone number is " + OK[0])
}

</SCRIPT>

Enter your phone number (with area code) and then press Enter.
<FORM>
<INPUT TYPE="text" NAME="Phone" onChange="testInfo(this);">
</FORM>

</HTML>