Мобильная версия

Электронная библиотека

Программисту веб-дизайнеру

Другие материалы

Клиентский JavaScript. Руководство по Использованию

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

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

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

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

  • Создание регулярного выражения
  • Написание патэрна регулярного выражения
  • Работа в регулярными выражениями
  • Примеры
  • Создание регулярного выражения

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

  • Используя инициализатор объекта:
  • re = /ab+c/
    Инициализаторы объектов выполняют компиляцию регулярного выражения при вычислении скрипта. Если регулярное выражение является константным, используйте инициализатор для повышения производительности. Инициализаторы объектов обсуждаются в разделе "Использование Инициализаторов Объектов".
  • Вызывая функцию-конструктор объекта RegExp:
  • re = new RegExp("ab+c")
    Использование функции-конструктора предоставляет компиляцию регулярного выражения на этапе прогона. Это делается, если известно, что патэрн регулярного выражения будет изменяться, или если Вы не знаете патэрн и получаете его из другого источника, такого как пользовательский ввод. После того как регулярное выражение определено, и если оно используется в скрипте и исходное значение изменяется, Вы можете использовать метод compile для компиляции нового регулярного выражения для более эффективного многократного использования.

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

    Патэрн регулярного выражения состоит из простых символов, например, /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'.

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

    Таблица 4.1 Специальные символы в регулярных выражениях


    Символ
    Значение
    \

    Один из следующих вариантов:

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

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

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

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

    ^

    Совпадает с началом ввода или строки.

    Например, /^A/ не совпадает с 'A' в строке "an A," но совпадает с первой А в строке "An A".

    $

    Совпадает с концом ввода или строки.

    Например, /t$/ не совпадает с 't' в "eater", но совпадает в "eat".

    *

    Предшествующий символ совпадает 0 или более раз.

    Например, /bo*/ совпадает с 'boooo' в "A ghost booooed" и с 'b' в "A bird warbled", но не совпадает в "A goat grunted".

    +

    Предшествующий символ совпадает 1 или более раз. Эквивалентно {1,}.

    Например, /a+/ совпадает с 'a' в "candy" and all the a's in "caaaaaaandy."

    ?

    Предшествующий символ совпадает 0 или 1 раз.

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

    .

    (Десятичная точка) совпадает с любым одиночным символом, кроме символа новой строки.

    Например, /.n/ совпадает с 'an' и с 'on' в "nay, an apple is on the tree", но не с 'nay'.

    (x)

    Совпадает с 'x' и запоминает совпадение.

    Например, /(foo)/ совпадает (и запоминает) с 'foo' в "foo bar." Совпавшая подстрока может быть вызвана из результирующего массива элементов [1], ..., [n] или из свойств $1, ..., $9 предопределенного объекта RegExp.

    x|y

    Совпадает с 'x' или с 'y'.

    Например, /green|red/ совпадает с 'green' в "green apple" и с 'red' в "red apple."

    {n}

    Где n это положительное целое. Предшествующий символ совпадает точно n раз.

    Например, /a{2}/ не совпадает с 'a' в "candy", но совпадает со всеми 'a' в "caandy" и с первыми двумя 'a' в "caaandy."

    {n,}

    Где n это положительное целое. Предшествующий символ совпадает как минимум n раз.

    Например, /a{2,} не совпадает с 'a' в "candy", но совпадает со всеми 'a' в "caandy" и в "caaaaaaandy."

    {n,m}

    Где n и m это положительные целые. Предшествующий символ совпадает как минимум n и максимум m раз.

    Например, /a{1,3}/ не совпадает ни с чем в "cndy", совпадает с 'a' in "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' in "noonday"; /\wy\b/ совпадает с 'ly' in "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].

    Например, /\s\w*/ совпадает с ' bar' в "foo bar".

    \S

    Совпадает с одиночным символом, отличным от пробела. Эквивалентно [^ \f\n\r\t\v].

    Например, /\S\w*/ совпадает с  'foo' в "foo bar."

    \t

    Совпадает с tab.

    \v

    Совпадает с vertical tab.

    \w

    Совпадает с любым алфавитно-цифровым символом, включая символ подчеркивания. Эквивалентно [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."
    Более сложный пример идет далее после таблицы.

    Примечание: Если количество левых скобок меньше числа, специфицированного в \n, то \n считается восьмеричной escape-последовательностью, как описано в следующем ряду.

    \ooctal
    \xhex

    Где \ooctal  это 8-ричное escape-значение или где \xhex  это 16-ричное escape-значение. Дает возможность внедрять ASCII-коды в регулярные выражения.

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

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

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

    Этот патэрн находит совпадение в "Open Chapter 4.3, paragraph 6", и '4' запоминается. Патэрн не находит совпадение в "Chapter 3 and 4", поскольку эта строка не содержит точку после '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>

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

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

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

    Таблица 4.3 Результаты выполнения регулярного выражения


    Объект
    Свойство или Индекс
    Описание
    В данном примере
    myArray

    Совпавшая строка и все запомненные подстроки.

    ["dbbd", "bb"]

    index

    Индекс с базой 0 совпадения в строке ввода.

    1

    input

    Строка-оригинал.

    "cdbbdbsbz"

    [0]

    Последние совпавшие символы.

    "dbbd"

    myRe
    lastIndex

    Индекс, по которому находится начало следующего совпадения. (Это свойство устанавливается, только если регулярное выражение использует опцию g, описанную в разделе "Выполнение Глобального Поиска и Игнорирование Регистра Символов".)

    5

    source

    Текст патэрна.

    "d(b+)d"

    RegExp
    lastMatch

    Последние совпавшие символы.

    "dbbd"

    leftContext

    Подстрока, предшествующая самому последнему совпадению.

    "c"

    rightContext

    Подстрока, идущая после самого последнего совпадения.

    "bsbz"

    RegExp.leftContext и RegExp.rightContext могут быть высчитаны из других значений.
    RegExp.leftContext
    эквивалентно:

    myArray.input.substring(0, myArray.index)

    а RegExp.rightContext эквивалентно:

    myArray.input.substring(myArray.index + myArray[0].length)

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

    <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. Если Вам нужен доступ к свойствам регулярного выражения, созданного инициализатором объекта, Вы должны сначала присвоить его переменной.

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

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

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

    Пример 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 в качестве аргумента. Заметьте, что RegExp обязан быть присоединен как префикс к его свойствам $ (поскольку они появляются вне замещающей строки). (Пример 3 это более эффективный, хотя, может быть, и более завуалированный способ сделать то же самое.)

    <HTML>
    <SCRIPT LANGUAGE="JavaScript1.2">
    function getInfo(){
    re = /(\w+)\s(\d+)/
    re.exec();
    window.alert(RegExp.$1 + ", your age is " + RegExp.$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. Но вместо использования RegExp.$1 и RegExp.$2 этот пример создает массив и использует a[1] и a[2]. Здесь используется также сокращенная нотация для метода exec.

    <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>

    Выполнение глобального поиска и игнорирование регистра символов

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

    Синтаксис для включения флага:

    re = /pattern/[g|i|gi]
    re = new RegExp("pattern", ['g'|'i'|'gi'])

    Заметьте, что флаги i и g являются неотъемлемой частью регулярного выражения. Они не могут быть добавлены и удалены позднее.

    Например, 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 = /\w+\s/g;

    на строку:

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

    и получить тот же самый результат.

    Примеры

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

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

    Это пример форматирования регулярных выражений и использования методов string.split() и string.replace(). Здесь зачищается грубо отформатированная строка ввода, содержащая имена (первое имя идет первым), разделенные пробелом, табуляцией и одним символом "точка с запятой". Затем порядок имен разворачивается (последнее имя идет первым) и список сортируется.

    <SCRIPT LANGUAGE="JavaScript1.2">
    // Строка name содержит несколько пробелов и табуляций,
    // и может иметь несколько пробелов между первым и последним именами.
    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 = /\s*;\s*/
    // Разбивка строки на куски, разделенные вышеуказанным патэрном,
    // и сохранение этих кусков в массиве nameList
    nameList = names.split (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>

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

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

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

    Оглавление | Назад | Вперед | Индекс

    Мобильная версия

    Сайт для компьютера
    http://www.mat.net.ua