Ядро JavaScript 1.5. Руководство по Использованию
Глава 4 Регулярные Выражения
Регулярные выражения являются патэрнами, используемыми при
поиске совпадений комбинаций символов в строках. В JavaScript регулярные
выражения являются также объектами. Эти патэрны используются вместе с методами exec
и test объекта RegExp и с методами match, replace, search и split объекта String.
В этой главе рассматриваются регулярные выражения JavaScript.
JavaScript 1.1 и ранее.
Регулярные выражения недоступны в JavaScript 1.1 и более ранних версиях.
В этой главе имеются следующие разделы:
- Создание Регулярного Выражения
- Написание Патэрна Регулярного Выражения
- Работа с Регулярными Выражениями
- Примеры
Создание Регулярного Выражения
Вы конструируете регулярное выражение одним из двух способов:
- Используя литерал регулярного выражения:
-
Литералы регулярного выражения дают возможность компилировать регулярное
выражение при вычислении скрипта. Когда регулярное выражение остается
постоянным, используете этот способ для повышения производительности.
-
Литералы регулярного выражения дают возможность компилировать регулярное
выражение при вычислении скрипта. Когда регулярное выражение остается
постоянным, используете этот способ для повышения производительности.
- Вызывая конструктор функции объекта RegExp:
- Использование конструктора функции дает возможность компилировать регулярное выражение на этапе прогона программы. Используйте конструктор функции, если Вам известно, что патэрн регулярного выражения будет изменяться или если Вы не знаете патэрн и получаете его из другого источника, такого как пользовательский ввод.
Написание Патэрна Регулярного Выражения
Патэрн регулярного выражения состоит из обычных символов, таких как /abc/, или из комбинаций обычных и специальных символов, таких как /ab*c/ или /Chapter (\d+)\.\d*/. В последнем примере есть скобки, которые используются в качестве запоминающего устройства. Совпадение этой части патэрна запоминается для последующего использования, как описано в разделе Использование Совпадений Подстрок в Скобках.
Использование Простых Патэрнов
Простые патэрны составляются из символов, для которых Вы ищете прямое совпадение. Например, патэрн /abc/ совпадает в строке только с точными комбинациями указанных символов 'abc' в указанном порядке. Такое совпадение произойдет в строках "Hi, do you know your abc's?" и "The latest airplane designs evolved from slabcraft." В обоих случаях совпадение произойдет с подстрокой 'abc'. В строке "Grab crab" совпадения не будет, поскольку она не содержит подстроки 'abc'.
Использование Специальных Символов
Если при поиске требуется нечто большее, чем простое совпадение, например, найти один или более символов b или найти пробел, в патэрн включаются специальные символы. Например, патэрн /ab*c/ совпадает с любой комбинацией символов, в которой после одиночной 'a' идет нуль или более символов 'b" (* означает 0 или более вхождений предшествующего элемента/символа) и сразу за ними - 'c'. В строке "cbbabbbbcdebc" этот патэрн совпадет с подстрокой 'abbbbc'.
В следующей таблице дан полный список и и описание специальных символов, используемых в регулярных выражениях.
Использование Скобок
Скобки вокруг любой части патэрна регулярного выражения вызывают запоминание этой части совпавшей подстроки. Затем эта подстрока может быть вызвана для последующего использования, как описано в разделе Использование Совпадений Подстроки в Скобках.
Например, патэрн /Chapter (\d+)\.\d*/ иллюстрирует использование дополнительных escape-ированных и специальных символов и указывает, что эта часть патэрна должна быть запомнена. Он совпадает точно с символами 'Chapter ' с последующими одним или более цифровыми символами (\d означает любой цифровой символ, а + означает 1 или более раз), с последующей десятичной точкой (которая сама по себе является специальным символом; предварение десятичной точки символом \ означает, что патэрн обязан искать специальный литеральный символ '.'), с последующим любым цифровым символом 0 или более раз(\d означает цифровой символ, * означает 0 или более раз). Кроме того, используются скобки для запоминания первых совпавших цифровых символов.
Этот патэрн будет найден в строке "Open Chapter 4.3, paragraph 6", и '4' будет запомнена. Патэрн не будет найден в строке "Chapter 3 and 4", поскольку здесь отсутствует десятичная точка после цифры '3'.
Чтобы найти совпадение с подстрокой без запоминания совпавшей части, предваряйте патэрн внутри скобок символами ?:. Например, (?:\d+) совпадает с единицей или числовым символом, но не запоминает совпавшие символы.
Работа с Регулярными Выражениями
Регулярные выражения используются с методами test и exec объекта RegExp и с методами match, replace, search и split объекта String.Эти методы рассматриваются в книге Ядро JavaScript. Справочник.
Если Вам нужно знать, найден ли патэрн в строке, используйте методы 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>
Если Вы хотите сконструировать регулярное выражение из строки, вот еще один скрипт:
<SCRIPT LANGUAGE="JavaScript1.2">
myRe= new RegExp ("d(b+)d", "g");
myArray = myRe.exec("cdbbdbsbz");
</SCRIPT>
С помощью этих скриптов находится совпадение и возвращается массив и обновляются свойства, показанные в следующей таблице.
Объект |
Свойство или Индекс | Описание | В этом примере: |
---|---|---|---|
myArray |
|||
index |
|||
input |
|||
[0] | |||
myRe |
lastIndex | Индекс, начиная с которого стартует следующее совпадение. (Это свойство установлено только тогда, когда регулярное выражение использует опцию g, описанную в разделе Выполнение Глобального Поиска, Игнорирование Регистра и Рассмотрение Многострочного Ввода.) | |
source |
Текст патэрна. Обновляется в момент создания регулярного выражения, не исполняется. |
Как показано во второй форме этого примера, Вы можете использовать регулярное выражение, созданное с помощью инициализатора объекта, без присвоения его переменной. Если Вы все же это сделаете, каждое вхождение будет новым регулярным выражением. Исходя из этого, если Вы используете форму без присвоения выражения переменной, Вы не сможете затем получить доступ к свойствам этого регулярного выражения. Например, у Вас есть скрипт:
<SCRIPT LANGUAGE="JavaScript1.2">
myRe=/d(b+)d/g;
myArray = myRe.exec("cdbbdbsbz");
document.writeln("The value of lastIndex is " + myRe.lastIndex);
</SCRIPT>
Если Ваш скрипт, однако, будет таким:
<SCRIPT LANGUAGE="JavaScript1.2">
myArray = /d(b+)d/g.exec("cdbbdbsbz");
document.writeln("The value of lastIndex is " + /d(b+)d/g.lastIndex);
</SCRIPT>
Вхождения /d(b+)d/g в этих двух операторах являются разными объектами регулярного выражения и, соответственно, имеют разные значения свойства lastIndex. Если Вам нужен доступ к свойствам регулярного выражения, созданного с помощью инициализатора объекта, Вы должны сначала присвоить это выражение переменной.
Использование Совпадений Подстрок в Скобках
Включение скобок в патэрн регулярного выражения вызывает запоминание соответствующего подсовпадения. Например, /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 в качестве аргумента.
<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>
Выполнение Глобального Поиска, Игнорирование Регистра и Рассмотрение Многострочного Ввода
Регулярные выражения могут иметь три опции-флага, дающие
возможность выполнять глобальный и нечувствительный к регистру поиск. Для
глобального поиска используйте флаг g
. Для поиска без учета
регистра используйте флаг i
. Для многострочного поиска - флаг m
.
Эти флаги могут использоваться независимо или вместе в любом порядке и являются
частью регулярного выражения.
Для включения флага используется следующий синтаксис:
re = /pattern/flags
re = new RegExp("pattern", ["flags"])
Обратите внимание, что флаги интегрированы в регулярное
выражение. Они не могут быть позднее добавлены или удалены.
Например, re = /\w+\s/g создает регулярное выражение, которое ищет один или более символов с последующим пробелом по всей строке.
<SCRIPT LANGUAGE="JavaScript1.2">
re = /\w+\s/g;
str = "fee fi fo fum";
myArray = str.match(re);
document.write(myArray);
</SCRIPT>
Отобразится ["fee ", "fi ", "fo "]. В этом примере Вы можете заменить строку:
re = new RegExp("\\w+\\s", "g");
и получить аналогичный результат.
Флаг m используется flag для специфицирования того, что многострочный ввод должен рассматриваться как несколько строк. Если используется флаг m, то ^ и $ совпадают в начале и в конце любой строки общей строки ввода, вместо начала и конца всей строки ввода.
Примеры
Несколько примеров использования регулярных выражений.
Изменение Порядка в Строке Ввода
В этом примере показано форматирование регулярного
выражения и использование методов 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>")
Использование Специальных Символов для Проверки Ввода
В этом примере пользователь вводит телефонный номер. Когда нажимается 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])
}
Enter your phone number (with area code) and then press Enter.
<FORM>
<INPUT TYPE="text" NAME="Phone" onChange="testInfo(this);">
</FORM>