Введение в регулярные выражения
Регулярное выражение (также называемое Regex для короткого) – это быстрый способ работы с строками текста.
Путем разработки регулярного выражения со специальным синтаксисом, вы можете:
- Поиск текста в строке
- Заменить подстроки в строке
- и Извлечь информацию от струны
Почти каждый язык программирования имеет некоторую реализацию регулярных выражений. Существуют небольшие различия между каждой реализацией, но общие концепции применяются почти везде.
Регулярные выражения датируются до 1950-х годов, когда они были формализованы как концептуальный шаблон поиска для алгоритмов обработки струн.
Реализовано в инструментах Unix, таких как GreeP, SED и в популярных текстовых редакторах, Regexes выросло популярностью. Они были введены в язык программирования PERL, а затем во многих других.
JavaScript наряду с PERL, является одним из языков программирования, которые имеют поддержку регулярных выражений, непосредственно встроенных в язык.
Тяжело, но полезно
Регулярные выражения могут показаться абсолютной ерундой для новичка, и много раз профессионального разработчика, если вы не вкладываете время, необходимое для их понять.
Криптовые регулярные выражения – Трудно написать , Трудно читать и Трудно поддерживать/изменить Отказ
Но иногда регулярное выражение – единственный вменяемый путь Для выполнения некоторых строковых манипуляций, так что это очень ценный инструмент в вашем кармане.
Это руководство направлено на то, чтобы познакомить вас с регулярными выражениями JavaScript простым способом, и предоставить вам всю информацию для чтения и создания регулярных выражений.
Правило, что Простые регулярные выражения просты для чтения И напишите , пока Комплексные регулярные выражения могут быстро превратиться в беспорядок Если вы не глубоко понимаете основы.
Как выглядит регулярное выражение?
В JavaScript регулярное выражение – это объект , который можно определить двумя способами.
Первый – это создание A Новый regexp объект Использование конструктора:
const re1 = new RegExp('hey')Второй использует регулярное выражение литерала форма:
const re1 = /hey/
Вы знаете, что имеет JavaScript объектные литералы и Массивные литералы ? Это также имеет Regex литералы Отказ
В приведенном выше примере Эй, называется узор Отказ В буквальной форме он разграничен пересылающими скольжениями, а с конструктором объекта, это не так.
Это первое важное различие между двумя формами, но мы увидим других позже.
Как это работает?
Регулярное выражение, которое мы определили как Re1 выше очень простой. Он ищет строку Эй, без каких-либо ограничений. Строка может содержать много текста, а Эй, В середине, и регулярное выражение удовлетворено. Это также может содержать только Эй, и Regex также будет удовлетворен.
Это довольно просто.
Вы можете проверить Regeex, используя Regexp.test (строка) , который возвращает логию:
re1.test('hey') //✅ re1.test('blablabla hey blablabla') //✅ re1.test('he') //❌ re1.test('blablabla') //❌В приведенном выше примере мы только что проверили, если "Эй" удовлетворяет регулярному образению экспрессии, хранящуюся в Re1. .
Это самый простой может быть, но теперь вы уже знаете много концепций о Regexes.
Закрепление
/hey/
Матчи Эй, Везде, где это было помещено внутри строки.
Если вы хотите сопоставить строки, которые Начать с Эй, Используйте ^ Оператор:
/^hey/.test('hey') //✅ /^hey/.test('bla hey') //❌Если вы хотите сопоставить строки, которые конец с Эй, Используйте $ Оператор:
/hey$/.test('hey') //✅ /hey$/.test('bla hey') //✅ /hey$/.test('hey you') //❌Объедините тех, и соответствуют строкам, которые точно совпадают Эй, и только эта строка:
/^hey$/.test('hey') //✅Чтобы сопоставить строку, которая начинается с подстроки и заканчивается другим, вы можете использовать Отказ * , который соответствует любому символу повторил 0 или более раз:
/^hey.*joe$/.test('hey joe') //✅ /^hey.*joe$/.test('heyjoe') //✅ /^hey.*joe$/.test('hey how are you joe') //✅ /^hey.*joe$/.test('hey joe!') //❌Матч элементы в диапазонах
Вместо того, чтобы соответствовать определенной строке, вы можете соответствовать любому символу в диапазоне, например:
/[a-z]/ //a, b, c, ... , x, y, z /[A-Z]/ //A, B, C, ... , X, Y, Z /[a-c]/ //a, b, c /[0-9]/ //0, 1, 2, 3, ... , 8, 9
Эти регулярные вещества сопоставляют строки, которые содержат хотя бы один из символов в этих диапазонах:
/[a-z]/.test('a') //✅ /[a-z]/.test('1') //❌ /[a-z]/.test('A') //❌ /[a-c]/.test('d') //❌ /[a-c]/.test('dc') //✅Диапазоны могут быть объединены:
/[A-Za-z0-9]/
/[A-Za-z0-9]/.test('a') //✅ /[A-Za-z0-9]/.test('1') //✅ /[A-Za-z0-9]/.test('A') //✅Соответствие пункте диапазона несколько раз
Вы можете проверить, содержит ли строка один и только один символ в диапазоне, используя - Char:
/^[A-Za-z0-9]$/
/^[A-Za-z0-9]$/.test('A') //✅ /^[A-Za-z0-9]$/.test('Ab') //❌Отрицание рисунка
^ Персонаж в начале шаблона привязывает его к началу строки.
Используется внутри диапазона, это отрицает Это , так:
/[^A-Za-z0-9]/.test('a') //❌ /[^A-Za-z0-9]/.test('1') //❌ /[^A-Za-z0-9]/.test('A') //❌ /[^A-Za-z0-9]/.test('@') //✅- \ D соответствует любой цифру, эквивалентной
[0-9] - \ D соответствует любому персонажу, который не является цифрой, эквивалентным
[^0-9] - \ W соответствует любому буквенно-цифровому символу, эквивалентно
[A-ZA-Z0-9] - \ W соответствует любому не буквенно-цифровым символом, эквивалентным
[^ A-za-z0-9] - \ S Соответствует любым пробелым персонажем: пробелы, вкладки, новинки и пробелы Unicode
- \ S соответствует любому персонажу, который не пробел
- \ 0 соответствует нулю
- \ N соответствует новой линии
- \ T соответствует вкладке
- \ uxxxx Соответствует символу Unicode с кодом XXXX (требуется флаг
uflag) - . Соответствует любому персонажу, который не является Newline Char (например
\ N) (Если вы не используете флагS, объясненные позже) - [^] соответствует любому символу, включая новых символов. Это полезно на многослойных струнах.
Регулярное выражение выбора
Если вы хотите найти одну строку или Другая Используйте |. оператор.
/hey|ho/.test('hey') //✅ /hey|ho/.test('ho') //✅Квантификаторы
Скажем, у вас есть это регулярное выражение, которое проверяет, имеет ли строка одной цифры в нем, и ничего больше:
/^\d$/
Вы можете использовать ? квантификатор Чтобы сделать его необязательным, таким образом, требующим нуля или одного:
/^\d?$/
Но что, если вы хотите подобрать несколько цифр?
Вы можете сделать это 4 способа, используя + , * , {n} и {n, m} Отказ Давайте посмотрим на них один за другим.
+
Соответствовать одному или нескольким) предметам
/^\d+$/
/^\d+$/.test('12') //✅ /^\d+$/.test('14') //✅ /^\d+$/.test('144343') //✅ /^\d+$/.test('') //❌ /^\d+$/.test('1a') //❌*
Матч 0 или более) предметы
/^\d+$/
/^\d*$/.test('12') //✅ /^\d*$/.test('14') //✅ /^\d*$/.test('144343') //✅ /^\d*$/.test('') //✅ /^\d*$/.test('1a') //❌{n}
Соответствовать точно n Предметы
/^\d{3}$/ /^\d{3}$/.test('123') //✅ /^\d{3}$/.test('12') //❌ /^\d{3}$/.test('1234') //❌ /^[A-Za-z0-9]{3}$/.test('Abc') //✅{n, m}
Соответствовать между n и м Время:
/^\d{3,5}$/ /^\d{3,5}$/.test('123') //✅ /^\d{3,5}$/.test('1234') //✅ /^\d{3,5}$/.test('12345') //✅ /^\d{3,5}$/.test('123456') //❌м может быть опущено, чтобы иметь открытое окончание, поэтому у вас есть как минимум n Предметы:
/^\d{3,}$/ /^\d{3,}$/.test('12') //❌ /^\d{3,}$/.test('123') //✅ /^\d{3,}$/.test('12345') //✅ /^\d{3,}$/.test('123456789') //✅Дополнительные элементы
После предмета с ? делает его необязательным:
/^\d{3}\w?$/ /^\d{3}\w?$/.test('123') //✅ /^\d{3}\w?$/.test('123a') //✅ /^\d{3}\w?$/.test('123ab') //❌Группы
Используя скобки, вы можете создавать группы символов: (...)
Этот пример соответствует ровно 3 цифра, а затем один или несколько буквенно-цифровых символов:
/^(\d{3})(\w+)$/ /^(\d{3})(\w+)$/.test('123') //❌ /^(\d{3})(\w+)$/.test('123s') //✅ /^(\d{3})(\w+)$/.test('123something') //✅ /^(\d{3})(\w+)$/.test('1234') //✅Символы повторения, поставленные после закрытия групп скользков, относятся к всей группе:
/^(\d{2})+$/ /^(\d{2})+$/.test('12') //✅ /^(\d{2})+$/.test('123') //❌ /^(\d{2})+$/.test('1234') //✅Захватные группы
До сих пор мы видели, как проверить строки и проверьте, содержат ли они определенный шаблон.
Очень крутая особенность регулярных выражений – это способность Захват частей струны и положите их в массив.
Вы можете сделать это, используя группы, а в частности Захватные группы Отказ
По умолчанию группа – это захватная группа. Теперь вместо использования Regexp.test (строка) , который просто возвращает логию, если шаблон доволен, мы используем либо String.match (Regexp) или Regexp.exec (строка) .
Они точно такие же, и вернут массив со всей сопоставленной строкой в первом элементе, затем каждый состав которого сопоставлен.
Если нет совпадения, он возвращает нулевой :
'123s'.match(/^(\d{3})(\w+)$/) //Array [ "123s", "123", "s" ] /^(\d{3})(\w+)$/.exec('123s') //Array [ "123s", "123", "s" ] 'hey'.match(/(hey|ho)/) //Array [ "hey", "hey" ]
/(hey|ho)/.exec('hey') //Array [ "hey", "hey" ] /(hey|ho)/.exec('ha!') //nullКогда группа совпадает с несколькими временами, только последний матч введен в массив результатов:
'123456789'.match(/(\d)+/) //Array [ "123456789", "9" ]
Дополнительные группы
Захватная группа может быть сделана необязательным с помощью (...)? . Если он не найден, полученный слот для массива будет содержать неопределенный :
/^(\d{3})(\s)?(\w+)$/.exec('123 s') //Array [ "123 s", "123", " ", "s" ] /^(\d{3})(\s)?(\w+)$/.exec('123s') //Array [ "123s", "123", undefined, "s" ]Ссылка сопоставленные группы
Каждая группа, которая подходит, присваивается номер. $ 1 Относится к первому, $ 2 во второй и так далее. Это будет полезно, когда мы говорим позже о замене частей строки.
Названные захватывающие группы
Это новый ES2018 характерная черта.
Группа может быть назначена на имя, а не просто назначать слот в результирующем массиве:
const re = /(?\d{4})-(? \d{2})-(? \d{2})/ const result = re.exec('2015-01-02')
// result.groups.year === '2015'; // result.groups.month === '01'; // result.groups.day === '02';
Использование Match и Exec без групп
Существует разница между использованием Матч и Exec Без групп: первый элемент в массиве не вся подходящая строка, а матч напрямую:
/hey|ho/.exec('hey') // [ "hey" ] /(hey).(ho)/.exec('hey ho') // [ "hey ho", "hey", "ho" ]Не захватывающие группы
Поскольку по умолчанию группы захватывают группы, вам нужен способ игнорировать некоторые группы в результирующем массиве. Это возможно, используя Незаптовые группы , который начинается с (?: ...)
'123s'.match(/^(\d{3})(?:\s)(\w+)$/)//null '123 s'.match(/^(\d{3})(?:\s)(\w+)$/) //Array [ "123 s", "123", "s" ]Флаги
Вы можете использовать следующие флаги на любом регулярном выражении:
g: соответствует шаблону несколько разЯ: делает нечувствительный случай Regexм: включает многослойный режим. В этом режиме^и$Сопоставьте начало и конец всей строки. Без этого, с многослойными струнами они соответствуют началу и конце каждой строки.U: позволяет поддерживать поддержку Unicode (введен в ES6/ES2015)S: (Новое в ES2018 ) Короче для Одна линия это вызываетОтказсоответствовать новым символам линии.
Флаги могут быть объединены, и они добавляются в конце строки в литералах Regex:
/hey/ig.test('HEy') //✅Или как второй параметр с конструкторами объектов Regexp:
new RegExp('hey', 'ig').test('HEy') //✅Проверяя регулярное выражение
Учитывая Regex, вы можете осмотреть его свойства:
ИсточникСтрока шаблонамногоровныйправда смфлагглобальныйправда сgфлагINGLORECASEправда сЯфлагLastIndex.
/^(\w{3})$/i.source //"^(\\d{3})(\\w+)$" /^(\w{3})$/i.multiline //false /^(\w{3})$/i.lastIndex //0 /^(\w{3})$/i.ignoreCase //true /^(\w{3})$/i.global //falseПобег
Эти персонажи особенные:
\/[ ]( ){ }?+*|.^$
Они особенные, потому что они управляют символами, которые имеют значение в шаблоне регулярного выражения. Если вы хотите использовать их внутри шаблона в качестве сопоставления символов, вам нужно избежать их, подготовив обратную косание:
/^\\$/ /^\^$/ // /^\^$/.test('^') ✅ /^\$$/ // /^\$$/.test('$') ✅Струнные границы
\ b и \ B Пусть вы проверяете, находится ли строка в начале или в конце слова:
- \ b соответствует набору символов в начале или в конце слова
- \ B соответствует набору символов, а не в начале или в конце слова
Пример:
'I saw a bear'.match(/\bbear/) //Array ["bear"] 'I saw a beard'.match(/\bbear/) //Array ["bear"] 'I saw a beard'.match(/\bbear\b/) //null 'cool_bear'.match(/\bbear\b/) //null
Заменить, используя регулярные выражения
Мы уже увидели, как проверить, содержит ли строка шаблон.
Мы также увидели, как извлечь части строки в массив, соответствующий шаблону.
Давайте посмотрим, как Заменить части строки основанный на рисунке.
Строка Объект в JavaScript имеет метод замены (), который можно использовать без регулярных выражений для выполнения Одиночная замена На строке:
"Hello world!".replace('world', 'dog') //Hello dog! "My dog is a good dog!".replace('dog', 'cat') //My cat is a good dog!Этот метод также принимает регулярное выражение в качестве аргумента:
"Hello world!".replace(/world/, 'dog') //Hello dog!
Используя g Флаг – это Единственный способ Чтобы заменить несколько вхождений в строке в ванильном JavaScript:
"My dog is a good dog!".replace(/dog/g, 'cat') //My cat is a good cat!
Группы давайте сделаем более причудливые вещи, как двигаться вокруг частей струны:
"Hello, world!".replace(/(\w+), (\w+)!/, '$2: $1!!!') // "world: Hello!!!"
Вместо того, чтобы использовать строку, вы можете использовать функцию, чтобы сделать даже фанжетские вещи. Он получит ряд аргументов, как тот, который возвращен String.match (Regexp) или Regexp.exec (строка) С ряд аргументов, которые зависит от количества групп:
"Hello, world!".replace(/(\w+), (\w+)!/, (matchedString, first, second) => { console.log(first); console.log(second); return `${second.toUpperCase()}: ${first}!!!` }) //"WORLD: Hello!!!"
Жадность
Говорят, что регулярные выражения являются жадный по умолчанию.
Что это значит?
Возьми это регеекс:
/\$(.+)\s?/
Предполагается извлечь количество доллара из строки:
/\$(.+)\s?/.exec('This costs $100')[1] //100Но если у нас есть больше слов после количества, он исчезает:
/\$(.+)\s?/.exec('This costs $100 and it is less than $200')[1] //100 and it is less than $200Почему? Потому что регулярное выражение после $ подписывает какие-либо персонажа с , + И он не остановится, пока он не достигнет конца строки. Тогда это заканчивается, потому что \ S? делает окончательное пространство по желанию.
Чтобы исправить это, нам нужно сообщить регелесу ленивым и выполнять наименьшее количество сопоставления. Мы можем сделать это, используя ? Символ после квантификатора:
/\$(.+?)\s/.exec('This costs $100 and it is less than $200')[1] //100Итак, ? означает разные вещи на основе его позиции, потому что он может быть как квантификатор, так и ленивый режим индикатора.
Lookaheads: сопоставьте строку в зависимости от того, что следует за этим
Использовать ? = Чтобы сопоставить строку, которая сопровождается определенной подстрокой:
/Roger(?=Waters)/
/Roger(?= Waters)/.test('Roger is my dog') //false /Roger(?= Waters)/.test('Roger is my dog and Roger Waters is a famous musician') //trueУдар Выполняет обратную работу, соответствие, если строка – не с последующим определенной подстрокой:
/Roger(?!Waters)/
/Roger(?! Waters)/.test('Roger is my dog') //true /Roger(?! Waters)/.test('Roger Waters is a famous musician') //falseСмотреть больше всего: сопоставить строку в зависимости от того, что предшествует этому
Это ES2018 характерная черта.
Lookaeads используют знак равно условное обозначение. Смотреть больше, используйте ? & l t; =. =.
/(?<=Roger) Waters/
/(?<=Roger) Waters/.test('Pink Waters is my dog') //false /(?<=Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //trueОБЕСПЕЧЕНИЕ отрицается, используя ? & l T;!:
/(?
/(?
/(?
Регулярные выражения и Unicode
U Флаг обязателен при работе с Unicode Strings. В частности, это относится, когда вам может потребоваться обработать персонажи в астральных плоскостях (те, которые не включены в первые 1600 символов Unicode).
Emojis – хороший пример, но они не единственный.
Если вы не добавите этот флаг, это простое регулярное выражение, которое должно соответствовать одному символу, не будет работать, поскольку для JavaScript Emoji представлен внутренне на 2 символа (см. Unicode в JavaScript ):
/^.$/.test('a') //✅ /^.$/.test('?') //❌ /^.$/u.test('?') //✅ Итак, всегда используйте u флаг.
Unicode, как обычные символы, обрабатывающие диапазоны:
/[a-z]/.test('a') //✅ /[1-9]/.test('1') //✅ /[?-?]/u.test('?') //✅ /[?-?]/u.test('?') //❌ JavaScript проверяет представление внутреннего кода, так что? потому что SE \ U1f. 436 < \ U1F. 43a < ; \ u1f98a. Слияние черт полный E. Moji Список, чтобы получить эти коды, и выяснить заказ (Совет: пикера MacOS Emoji имеет некоторые эмохисы в смешанном порядке, поэтому не рассчитывайте на него).
Свойство Unicode уходит
Как мы видели выше, в шаблоне регулярного выражения вы можете использовать \d соответствовать любой цифре, \s соответствовать любому персонажу, который не является белым пространством, \w соответствовать любому буквенно-цифровому символу и так далее.
Свойство Unicode Essapes является ES2018. Функция, которая вводит очень классную функцию, расширяя эту концепцию для всех символов Unicode, представляющих \p{} а также его отрицание \P{} .
Любой символ Unicode имеет набор свойств. Например Скрипт определяет языковую семью, Ascii Это логическое значение, которое верно для персонажей ASCII и так далее. Вы можете поставить это свойство в графические скобки, а Regeex проверит, чтобы быть правдой:
/^\p{ASCII}+$/u.test('abc') //✅ /^\p{ASCII}+$/u.test('ABC@') //✅ /^\p{ASCII}+$/u.test('ABC?') //❌ Ascii_hex_digit. Это еще одно логическое свойство, которое проверяет, содержит ли строка только в действительности шестнадцатеричных цифр:
/^\p{ASCII_Hex_Digit}+$/u.test('0123456789ABCDEF') //✅ /^\p{ASCII_Hex_Digit}+$/u.test('h') //❌Есть много других логических свойств, которые вы просто проверяете, добавив их имя в графические скобки, в том числе Верхний регистр , Нижний регистр , White_space. , Алфавит , Emoji и более:
/^\p{Lowercase}$/u.test('h') //✅ /^\p{Uppercase}$/u.test('H') //✅ /^\p{Emoji}+$/u.test('H') //❌ /^\p{Emoji}+$/u.test('??') //✅ В дополнение к этим двоичным свойствам вы можете проверить любой из свойств символов Unicode для соответствия определенному значению. В этом примере я проверяю, написана ли строка на греческом или латинском алфавите:
/^\p{Script=Greek}+$/u.test('ελληνικά') //✅ /^\p{Script=Latin}+$/u.test('hey') //✅Узнайте больше о всех свойствах вы можете использовать непосредственно на предложение .
Примеры
Предположим, что строка имеет только одно число, которое вам нужно для извлечения, /\d+/ должен сделать это:
'Test 123123329'.match(/\d+/) // Array [ "123123329" ]
Сопоставьте адрес электронной почты
Упрощенный подход – проверять не пространство персонажей до и после @ знак, используя \S :
/(\S+)@(\S+)\.(\S+)/
/(\S+)@(\S+)\.(\S+)/.exec('copesc@gmail.com') //["copesc@gmail.com", "copesc", "gmail", "com"]Это упрощенный пример, однако, как многие недействительные электронные письма все еще довольны этим Regex.
Захватить текст между двойными цитатами
Предположим, у вас есть строка, которая содержит что-то в двойных кавычках, и вы хотите извлечь этот контент.
Лучший способ сделать это, используя Захват группы , потому что мы знаем, что матч начинается и заканчивается ” И мы можем легко нацелиться, но мы также хотим удалить эти цитаты из нашего результата.
Мы найдем то, что нам нужно в Результат [1] :
const hello = 'Hello "nice flower"' const result = /"([^']*)"/.exec(hello) //Array [ "\"nice flower\"", "nice flower" ]
Получить контент внутри тега HTML
Например, получить контент внутри метка SPAN, позволяя любому количеству аргументов внутри тега:
/]*>(.*?)<\/span>/ /]*>(.*?)<\/span>/.exec('test')// null /]*>(.*?)<\/span>/.exec('test') // ["test", "test"] /]*>(.*?)<\/span>/.exec('test') // ["test", "test"]Оригинал: “https://www.freecodecamp.org/news/a-quick-and-simple-guide-to-javascript-regular-expressions-48b46a68df29/”