- Онлайн песочница: regex101.
- Интерактивное обучение: regexlearn.com
Регулярные выражения — это специальным образом записанные строки, используемые для поиска символьных шаблонов в тексте. Их можно использовать для инструментов командной строки, например, grep.
.
- точка соответствует любому символу, например,gr.y
найдет строки "gray", "green", "groom".^
- символ начала строки, например,^hello
найдет строки, начинающиеся с "hello".$
- символ конца строки, например,world$
найдет строки, заканчивающиеся на "world".[]
- определяет класс символов, например,[aeiou]
найдет любую гласную букву,[0-9]
найдет любую цифру.[^]
- отрицание класса символов, например,[^0-9]
найдет любой символ, кроме цифр.*
- символ, обозначает необязательный элемент, например,abc*
найдет "ab", "abc", "abcc", "abccc", и т.д.+
- символ, действующий почти так же, как*
, но требует совпадения с предыдущим элементом не менее одного раза, например,abc+
найдет "abc", "abcc", "abccc", и т.д.?
- символ, означающий совпадение с элементом ноль или один раз. Иными словами совпадение с предыдущим элементом необязательно, например,ab?c
найдет "ac" и "abc".()
- используются для группировки выражений, например,(ab)+
найдет "ab", "abab", "ababab", и т.д.\
- используется для экранирования специальных символов, например,\.
найдет точку в тексте.
Квантификаторы
В регулярных выражениях квантификаторы указывают, сколько раз должен встретиться символ. Вот список квантификаторов:
a|b
- или a, или b?
- ноль или один+
- один или больше*
- ноль или больше{N}
- ровно N раз (здесь N - число){N,}
- N или больше раз (N - число){N,M}
- от N до M раз (N и M - числа, при этом N < M)*?
- ноль или больше, но после первого совпадения поиск нужно прекратить
Например, следующее регулярное выражение соответствует и строке «Hello», и строке «Goodbye»:
Hello|Goodbye
В то время как
Hey?
Может означать как отсутствие y, так и одно вхождение y, и таким образом весь шаблон может соответствовать и «He», и «Hey».
Еще пример:
Hello{1,3}
Этот шаблон соответствует «Hello», «Hellooo», но не «Helloooo», потому что буква «о» может встречаться от 1 до 3 раз.
Квантификаторы можно комбинировать:
He?llo{2}
Здесь мы ищем строки, в которых «e» нет или встречается 1 раз, а «o» встречается ровно 2 раза. Таким образом, этот шаблон соответствует словам «Helloo» и «Hlloo».
Наборы
Квадратные скобки позволяют искать совпадение по целому набору символов, указанному в скобках. Например, шаблон
My favorite vowel is [aeiou]
Совпадет со строками:
My favorite vowel is a
My favorite vowel is e
My favorite vowel is i
My favorite vowel is o
My favorite vowel is u
И ни с чем другим. [aeiou]
- это набор, в регулярном выражении означающий «любой из указанных символов».
Вот список самых распространенных наборов:
[A-Z]
- совпадает с любой буквой в верхнем регистре, от «A» до «Z»[a-z]
- совпадает с любой буквой в нижнем регистре, от «a» до «z»[0-9]
-любая цифра[asdf]
- совпадает с «a», «s», «d» или «f»[^asdf]
- совпадает с любым символом кроме «a», «s», «d» или «f»
Эти наборы можно комбинировать:
[0-9A-Z]
- любой символ, являющийся либо цифрой, либо буквой от A до Z[^a-z]
- любой символ, не являющийся буквой латинского алфавита в нижнем регистре
Символьные классы
Не каждый символ можно так легко идентифицировать. Скажем, найти буквы с использованием regex легко, а как насчет символа новой строки?
Примечание. Символ новой строки - это символ, который вы вводите, когда нажимаете Enter и переходите на новую строку.
.
- любой символ\n
- символ новой строки\t
- символ табуляции\s
- пробельный символ (включая \t, \n и некоторые другие)\S
- не-пробельный символ\w
- любой «словообразующий» символ (буквы латинского алфавита в верхнем и нижнем регистре, цифры 0-9 и символ подчеркивания_
)\W
- любой «несловообразующий» символ (класс символов, обратный классу \w)\b
- граница слова, разделяет\w
и\W
, т. е. словообразующие и несловообразующие символы. Граница слова соответствует позиции, где за символом слова не следует другой символ слова.\B
- несловообразующая граница (класс, обратный\b
). Несловообразующая граница соответствует позиции, в которой предыдущий и следующий символы являются символами одного типа: либо оба должны быть словообразующими символами, либо несловообразующими. Начало и конец строки считаются несловообразующими символами.^
- начало строки$
- конец строки\\
- символ «\» в буквальном значении
Допустим, вы хотите удалить каждый символ, с которого начинается новое слово в строке. Вы можете использовать следующее регулярное выражение для поиска этих символов:
\s.
А затем найденные символы можно заменить пустой строкой. Таким образом строка
Hello world how are you
Превратится в
Helloorldowreou
Комбинирование наборов
Символьные классы сами по себе не слишком полезны, но их можно сочетать с наборами. Допустим, мы хотим удалить из строки любую букву в верхнем регистре или пробельный символ. Это можно написать так:
[A-Z]|\s
Но \s
можно поместить и внутрь набора:
[A-Z\s]
Границы слова
В списке символьных классов вы видели символ \b
, означающий границу слова. На нем стоит остановиться отдельно, потому что этот токен работает не как остальные.
Допустим, у вас есть строка «This is a string». Вы можете предположить, что символ границы слова соответствует пробелам между словами, но это не так. Он соответствует тому, что находится между буквой и пробелом.
Это может быть трудно понять. Но обычно никто и не ищет сами границы слов. Вместо этого можно написать, например, выражение для поиска целых слов:
\b\w+\b
Это регулярное выражение интерпретируется следующим образом: «Граница слова, за которой следует один или больше словообразующих символов, за которыми следует другая граница слова».
Начало и конец строки
Еще два важных токена - ^
и $
. Они означают начало и конец строки соответственно.
То есть, если вы хотите найти первое слово в строке, вы можете написать следующее выражение:
^\w+
Оно соответствует одному или большему числу словообразующих символов, но только если они идут непосредственно в начале строки. Помните, что словообразующий символ это любая буква латинского алфавита в любом регистре, а также любая цифра и символ подчеркивания.
Аналогично, если вы хотите найти последнее слово в строке, ваше регулярное выражение может выглядеть так:
\w+$
Но то, что символ $
обычно заканчивает строку, не означает, что после него не может идти других символов.
Допустим, мы хотим найти каждый пробельный символ между новыми строками для создания базового минификатора JavaScript-кода.
Мы можем написать следующее выражение, чтобы найти все пробелы после конца строки:
$\s+
Экранирование символов
Хотя токены символьных классов очень полезны, иногда с ними возникают сложности. Например, когда нужно написать шаблон для поиска таких токенов в тексте.
Допустим, у вас есть строка в тексте статьи:
"Символ новой строки - '\n'"
Или вы хотите найти вообще все упоминания «\n» в тексте. Тогда в шаблоне символ \n
нужно «экранировать»: поставить перед ним обратную косую черту:
\\n
Замена строк при помощи регулярных выражений
Вы можете использовать regex для поиска и замены содержимого файлов. Скажем, вы хотите заменить любое приветствие на прощание. Можно сделать это так:
function youSayHelloISayGoodbye(str) {
str = str.replace("Hello", "Goodbye");
str = str.replace("Hi", "Goodbye");
str = str.replace("Hey", "Goodbye"); str = str.replace("hello", "Goodbye");
str = str.replace("hi", "Goodbye");
str = str.replace("hey", "Goodbye");
return str;
}
Но можно и проще, с использованием regex:
function youSayHelloISayGoodbye(str) {
str = str.replace(/[Hh]ello|[Hh]i|[Hh]ey/, "Goodbye");
return str;
}
Флаги в regex
Флаг - это модификатор существующего регулярного выражения. При определении regex флаги всегда добавляются после замыкающего слэша.
Вот небольшой список доступных флагов:
g
- глобально, больше одного совпаденияm
- заставляет$
и^
соответствовать каждой новой строчке отдельноi
- делает regex нечувствительным к регистру
Мы можем взять наше регулярное выражение:
/[Hh]ello|[Hh]i|[Hh]ey/
и переписать его, применив флаг нечувствительности к регистру:
/Hello|Hi|Hey/i
Это регулярное выражение будет соответствовать следующим словам:
Hello
HEY
Hi
HeLLo
Также оно будет соответствовать любому другому варианту чередования заглавных и строчных букв.
Флаг глобального поиска для замены строк
Как уже говорилось, если вы производите замену при помощи regex без всяких флагов, заменен будет только первый результат поиска:
let str = "Hello, hi there!";
str = str.replace(/[Hh]ello|[Hh]i|[Hh]ey/, "Goodbye");
console.log(str); // В выводе будет "Goodbye, hi there"
Но если вы добавите флаг глобального поиска, будут найдены все соответствия шаблону:
let str = "Hello, hi there!";
str = str.replace(/[Hh]ello|[Hh]i|[Hh]ey/g, "Goodbye");
console.log(str); // В выводе будет "Goodbye, Goodbye there"