| Поиск Google | Внутренний поиск | Библиотека бесплатного софта |
|
17 Июля 2010
Размещено
Статьи -
JavaScript
|
Сегодня практически каждый программист должен знать, что такое регулярные выражения (RegExp, RegEx). Их использование позволяет сократить громоздкий и трудночитаемый код до нескольких строчек. |
Содержимое
- Что такое регулярные выражения (RegExp) в JavaScript
- Представление символов и метасимволов
- Наборы символов (символьные классы)
- Позиционирование маски поиска
- Поиск последовательностей (квантификация)
- Ленивая и жадная квантификации
- Группировка
- Обратная связь
- Просмотр вперед и назад
- Использование регулярных выражений (RegExp) JavaScript
- Дополнительно
Что такое регулярные выражения (RegExp) в JavaScriptК оглавлению
Регулярные выражения используются для поиска подстрок текста по заданному шаблону (маске), состоящего из символов и метасимволов. Эта технология получила свою популярность после включения её в состав стандартных утилит Unix-систем, что привело к прорыву в электронной обработке текстов.
Давайте познакомимся с регулярными выражениями на примере. Допустим, у нас есть какая-то строка.
В переменной pattern мы указали маску в виде /кo./. Это как обычная строка, только заключена не в кавычки, а в символы "/".
В данном случае, мы указали, что ищем в строке три символа: первых два будут "ко", а третий может быть любым. Точка - это специальный метасимвол, который говорит, что на его месте может стоять любой из существующих символов.
В итоге скрипт нашел в строке первое совпадение с шаблоном. Тогда возникает вопрос - а почему же результатом не будет строчка "Кош"? Все просто, шаблон поиска чувствителен к регистру букв, а значит "Кош" и "кош" будут разными строками. А та маска, которую мы создали, подходит только для второго случая... Чтоб скрипт игнорировал регистр символов, надо добавить специальный атрибут (ignoreCase) к маске:
Теперь поиск будет осуществляться без учета регистра символов, и после выполнения скрипта мы увидим "Кош". Стоп, ведь мы нашли только первое вхождение данной подстроки, как нам найти все подстроки подходящие под шаблон поиска?
Все просто, нужно добавить еще один атрибут (global) к маске поиска и тогда мы сможем вызывать методе exec множество раз для поиска дальнейших совпадений. Причем индекс найденной подстроки будет находиться в переменной index:
Теперь в браузере мы увидим такой результат:
Кош - начинается с 0-го символа Дальше поиск начнется с 3-го символа кор - начинается с 8-го символа Дальше поиск начнется с 11-го символа кот - начинается с 22-го символа Дальше поиск начнется с 25-го символа
Маску поиска и её параметры можно также указывать через конструктор объекта RegExp:
Представление символов и метасимволовК оглавлению
Основная часть символов представляют сами себя в маске поиске за исключением ()[]\^$|?+. Чтобы отобразить их в виде строковых символов необходимо заэкранировать их слешем: "\." - точка, "\?" - знак вопроса, "\\" - левый слеш, и тд...
Кроме этого существуют еще набор метасимволов, которые набираются со слешем, вот они:
| Символ | Значение |
| \w | Этот метасивол показывает, что вместо него может стоять любой латинский символ словаря, включая буквы, цифры и знак подчеркивания. То есть, шаблон /\wat/ означает "bat", "rat", "0at", "_at" и тд. |
| \W | А это будет полной противоположностью предыдущего метатега. Он задает шаблон поиска несловарных (латинских) символов. /\Wat/ будет "$at", "?at"... |
| \d | Обозначает любой цифровой символ. /\dat/: "5at", "2at"... |
| \D | Любой НЕцифровой символ. /\Dat/: "rat", "cat"... |
| \s | Обозначает пробелы, табуляцию, перевод строки и другие юникодные пробельные символы. |
| \S | Все НЕпробельные символы. |
| \n,\r,\f | Соответствует спецсимволам перевод строки, line-feed и form-feed соответственно. |
| \t,\v | Задают символ горизонтальной и вертикальной табуляции. |
| \xhh | Задает символ с кодом hh (2 шестнадцатеричные цифры). |
| \uhhhh | Найдет символ с кодом hhhh (4 шестнадцатеричных цифры). |
Наборы символов (символьные классы)К оглавлению
С помощью квадратных скобок [] можно перечислить те символы, которые могут находиться в маске поиске. Например, f[a4_]s дает знать интерпретатору, что слово может иметь такие представления: fas, f4s или f_s.
Также можно через дефис указать диапазон символов, которые могут там стоять. [a-z123@] - все буквы латинского алфавита или цыфры 1,2,3 или собачка.
Если необходимо исключить какой-то символ, то перед ним ставится "^": [^a-z] - означает любой символ кроме букв латинского алфавита...
Мы уже использовали его ранее, но хочу еще раз напомнить, что метасимвол точка "." задает любой возможный символ. Его можно использовать без квадратных скобок.
Позиционирование маски поискаК оглавлению
Замечательной особенностью является возможность указать в каком месте слова или строки находится интересуемый нас шаблон. Указав "cat$" мы сможем найти слово cat, которое находится в самом конце строки. С Вашего позволения я скопирую сюда довольно подробную и интересную таблицу с википедии:
| Метасимвол | Позиционирование | Пример | Соответствие |
| ^ | Начало строки | ^b | bbb bbb |
| $ | Конец строки | b$ | bbb bbb |
| \b | Граница слова | b\b | bbb bbb |
| \bb | bbb bbb | ||
| \B | Не граница слова | \Bb\B | bbb bbb |
Поиск последовательностей (квантификация)К оглавлению
С помощью скобок {} можно задавать сколько раз будет повторяться символ стоящий перед ним (в том числе класс или группа). Приведенная ниже таблица поможет Вам разобраться с синтаксисом:
| Представление | Число повторений | Пример | Соответствие |
| {n} | Ровно n | ca{3}t | caaat |
| {m,n} | От m до n включительно | ca{2,4}t | caat, caaat, caaaat |
| {m,} | Не менее m | ca{2,}t | caat, caaat, caaaat и т.д. |
| {,n} | Не более n | ca{,3}t | ct, cat, caat, caaat |
Полный синтаксис используют довольно редко, когда нужно сделать сложную маску. На практике в основном используют краткую запись квантификаторов:
| Представление | Число повторений | Эквивалент | Пример | Соответствие |
| * | Ноль или более | {0,} | ca*t | ct, cat, caat, caaat и т.д. |
| + | Одно или более | {1,} | ca+t | cat, caat и т.д. (но не ct) |
| ? | Ноль или одно | {0,1} | ca?t | ct или cat |
Очень часто используют комбинацию ".*", что означает любую последовательность символов между тем, что стоит слева и справа в маске.
Если символы {} не образуют квантификатор, то их особое значение игнорируется, и они считаются обычными символами.
Ленивая и жадная квантификацииК оглавлению
Жадность - это стремление интерпретатора захватить максимально длинную строку, которая соответствует шаблону. Например, у нас есть строка:
z = 2 * (x + y) * (x - y)
Если мы хотим получить выражение в первых скобках, то попробуем задать вот такую маску: /\(.*\)/. Результат будет таким:
(x + y) * (x - y)
Обуздать жадность интерпретатора можно двумя способами:
1. В маске запретить двигаться дальше одной закрывающей скобки - /\([^\)]*\)/.
2. Воспользоваться ленивым квантификатором, добавив знак вопроса после звездочки - /\(.*?\)/.
После чего результат будет таким как мы и хотели:
(x + y)
Однако надо быть осторожным. Использование ленивых квантификаторов может повлечь за собой обратную проблему, когда найденному результату соответствует слишком короткая строка (в частности пустая).
| Жадный | Ленивый |
| * | *? |
| + | +? |
| {n,} | {n,}? |
К сожалению, алгоритм поиск последовательностей в регулярных выражениях очень громоздкий - он имеет рекурсивный вид. Чтобы избежать ненужных итераций обычно используют ревнивые квантификаторы (сверхжадные). Но JavaScript, почему-то, их не поддерживает.
ГруппировкаК оглавлению
Заключив некоторую последовательность в "(?:шаблон)" мы сможем применять к ней квантификаторы. Например, /(?:пр[ау]м-?)*/ найдет строку:
прам-прам-прумпрам-прум-прампрум
Также довольно полезным является оператор перечисления - "|". Указав шаблон /сra(?:ck|sty)/, интерпретатор сначала попробует найти "crack", а потом "crasty". Главное не забыть, что порядок указывается слева на право...
В регулярных выражениях также можно использовать комментарии в виде /ab(?#комментарий)c/, но JavaScript НЕ поддерживает эту возможность.
Обратная связьК оглавлению
Обратная связь позволяет запоминать отдельные подшаблоны в массиве для дальнейшего их использования. Для поиска с обратной связью нужно заключить подшаблон в круглые скобки ().
К примеру, воспользуемся таким шаблоном /c(a)t/. В результате поиска интерпретатор вернет массив с элементами cat и a (нумерация с нуля). В нулевой ячейке хранится результат поиска, а в первой - найденный в скобках подшаблон.
Массив формируется по порядку первого нахождения во время поиска. А значит, мы можем обращаться к этому массиву при задании шаблона. Значения массива получаем с помощью метасимволов от \1 до \9.
Маска /(пум|пам)-\1/ найдет строчку "пум-пум" или "пам-пам". Но не "пум-пам" и не "пам-пум"!
Просмотр вперед и назадК оглавлению
В возвращаемый результат можно не включать ненужные условия поиска, но только если они стоят перед или после искомой строки. Чтобы разобраться, давай посмотрим такую таблицу:
| Представление | Просмотр | Пример | Соответствие |
| (?=шаблон) | Вперёд | Петр(?=I) | Петр, ПетрI, ПетрII |
| (?!шаблон) | Вперёд с отрицанием | Петр(?!I) | Петр, ПетрI, ПетрII |
| (?<=шаблон) | Назад | (?<=Петр)I | Петр, ПетрI, ПетрII |
| (?<!шаблон) | Назад с отрицанием | (?<!Петр)I | Петр, ПетрI, I |
Использование регулярных выражений (RegExp) JavaScriptК оглавлению
Сейчас, когда необходимый шаблон уже присвоен объекту RegExp, что же с ним делать дальше? Существует два пути применения регулярных выражений. Первый заключается в использовании объекта RegExp, а второй - в использовании методов объекта String.
Ниже представлены методы объекта RegExp, которые обеспечивают поиск по шаблону. Обратите внимание, эти методы требуют передачи в качестве аргумента объекта String, в котором выполняется поиск.
| Метод | Описание |
| RegExp.exec(str) | Осуществляет поиск по заданному шаблону в строке str и возвращает результат. |
| RegExp.test(str) | Осуществляет поиск по заданному шаблону в строке str и возвращает true, если совпадение найдено и false - в противном случае. |
В следующей таблице показаны методы объекта String, которые позволяют выполнить поиск по шаблону. Все они требуют передачи в качестве параметра объект RegExp, в котором осуществляется поиск.
| Метод | Описание |
| String.search(regExpObj,str) | Возвращает позицию вхождения шаблона regExpObj внутри строки. |
| String.match(regExpObj) | Осуществляет поиск шаблона regExpObj внутри строки и возвращает результат. |
| String.replace(regExpObj,str) | Заменяет все вхождения шаблона regExpObj на str. |
Метод RegExp.test( String )
Используется для проверки существования строки указанной в шаблоне. Например:
Метод RegExp.exec( String )
Он возвращает массив и выставляет свойства регулярного выражения, по которому осуществлялся поиск. Если совпадение не найдено, то он возвращает null.
Например,
В результате работы этого скрипта будут такие результаты:
| Объект | Свойство/Индекс | Описание | Пример |
| result | Содержимое result | ["caAc", "aA", "c"] | |
| index | Индекс совпадения (от 0) | 1 | |
| input | Исходная строка. | ncaAcasaz | |
| [0] | Последние совпавшие символы | caAc | |
| [1], ...[n] | Совпадения во вложенных скобках, если есть. Число вложенных скобок не ограничено. | [1] = aA [2] = c |
|
| pattern | lastIndex | Индекс, с которого начинать следующий поиск. | 5 |
| ignoreCase | Показывает, что был включен регистронезависимый поиск, флаг "i". | true | |
| global | Показывает, что был включен флаг "g" поиска всех совпадений. | true | |
| multiline | Показывает, был ли включен флаг многострочного поиска "m". | false | |
| source | Текст паттерна. | c(a+)(c) |
Метод String.search( RegExpObj )
Осуществляет поиск регулярного выражения в строке и возвращает его индекс ( аналог RegExp.test() ).
Метод String.match( RegExpObj )
Если в маске поиска нет флага g, то этот метод возвращает тот же результат что и RegExp.exec().
Если же флаг присутствует в шаблоне, то возвращает массив со всеми совпадениями.
Функция вернет массив "Кош,кор,кот".
Метод String.replace( RegExpObj, String )
Это одна из самых интересных функций, в которой можно использовать регулярные выражения. Функция не меняет строку, к которой применяется, а просто возвращает результат. Она имеет два параметра:
Это одна из стандартных функций объекта String. И, к счастью, можно вместо обычных строк использовать регулярные выражения. Вторым параметром можно передавать даже функцию.
В результате мы получим такую строку "Кошка по0мила своих котят".
Чтобы заменились все совпадения в строке, нужно добавить еще параметр global к шаблону поиска:
Кроме этого функция позволяет использовать параметры, которые возвращаются в результате поиска с обратной связью.
Этот сценарий выведет текст: "Пушкин, Александр". Ниже привожу таблицу метасимволов, которые можно использовать в строке замены:
| Метасимвол | Описание |
| $$ | Вставляет "$". |
| $& | Вставляет найденную подстроку. |
| $` | Вставляет часть строки, которая предшествует найденному вхождению. |
| $' | Вставляет часть строки, которая идет после найденного вхождения. |
| $n or $nn | Где n или nn - десятичные цифры, вставляет подстроку вхождения, запомненную n-й вложенной скобкой, если первый аргумент - объект RegExp. |
ДополнительноК оглавлению
Для общего понимания регулярных выражений советую Вам почитать статью из википедии.
Более подробно они описаны в книге (англ.) Beginning Regular Expressions.


Комментарии