Regex или регулярные выражения пугают новичков, но необходимы любому программисту. Давайте разберемся в регулярных выражениях на 5 простых примерах с JavaScript.
Если у вас есть проблема и вы собираетесь решить ее регулярными выражениями – теперь у вас две проблемы. Есть такая поговорка. Регулярные выражения встречающиеся в коде, порой вызывают страх и ненависть у людей, которые с ними не знакомы.
Но фактически, любой regex – это всего лишь шаблонное выражение, способное в одну строку решить задачу целой функции. Однако для построения регулярного выражения необходимо учитывать набор строгих правил, в которых новичок может запутаться и ошибиться.
Совпадающие символы
Самые базовые регулярные выражения это те, что ищут совпадения по одному символу. Вот их правила:
1. Точка ( . ) соответствует любому символу. Если нужно искать именно точку, ее необходимо экранировать с помощью символа «\» ( \. ).
2. Знак вопроса ( ? ) означает, что предыдущий символ является необязательным. Чтобы искать сам знак вопроса в строке, его также необходимо экранировать с помощью «\» ( \? ).
var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu.'; // Подойдут оба и "elit", и "elat". Точка означает, что подойдет любой символ. var regex = /el.t/g; console.log( text.match(regex) ); // "est" и "lest" одинаково подойдут. Знак вопроса делает "l" необязательной. var regex2 = /l?est/g; console.log( text.match(regex2) );
Совпадение множества символов
Множество – это один или несколько символов, заключенных в скобки, например [abc]. Такое выражение будет искать в строке только этот набор символов – в данном примере только a, b или c. Можно наоборот, искать вхождения любых символов, кроме [abc] с помощью символа «^». [^ abc] будет соответствовать любому символу, который не является a, b или c. Также можно указать диапазон символов или чисел, например [0-9], [a-z].
Существуют встроенные наборы символов, упрощающие запись регулярных выражений. Их называют сокращениями или shorthand. К примеру, вместо [0-9] можно написать \D. Есть сокращения и для остальных символов (включая цифры и знак подчеркивания) – \w и \W, а также для пробелов – \s и \S.
// Подойдут только "cat" и "can", но не "car".
var text = 'cat car can';
console.log( text.match(/ca[tn]/g) );
// Пройдет все, кроме cat и can (присутствует символ ^ )
console.log( text.match(/ca[^tn]/g) );
// Еще один пример, где пройдут только цифры
text = 'I would like 8 cups of coffee, please.';
console.log('How many cups: ' + text.match( /[0-9]/g ));
// Более простой способ с помощью сокращения \d
console.log('How many cups: ' + text.match( /\d/g ));
// Пройдет все, кроме цифр
console.log( text.match(/\D/g) );
Совпадающие слова
В большинстве случаев вам нужно искать целые слова, а не отдельные символы. Это делается с помощью модификаторов ( + ) и ( - ), которые повторяют символ или набор символов.
Добавление {X} задает точное количество повторений, {x, y} – диапазон (x и y - числа).
Кроме того, есть специальный шаблон \b, который соответствует границам на концах слов.
Примеры:
var text = 'Hello people of 1974. I come from the future. In 2014 we have laser guns, hover boards and live on the moon!';
// Найдет годы. \d+ найдет один и более знаков
var yearRegex = /\d+/g;
console.log('Years: ', text.match( yearRegex ) );
// Найдет все предложения. Наши предложения начинаются с заглавной буквы, а кончаются точкой или восклицательным знаком.
var sentenceRegex = /[A-Z].+?(\.|!)/g;
console.log('Sentences: ', text.match(sentenceRegex) );
// Найдет все слова, начинающиеся на "h". Нам подойдут и заглавные и строчные, так что используем модификатор i
// \b для определения границы слов.
var hWords = /\bh\w+/ig;
console.log('H Words: ', text.match(hWords) );
// Найдет все слова от 4 до 6 символов
var findWords = /\b\w{4,6}\b/g;
console.log( 'Words between 4 and 6 chars: ', text.match(findWords) );
// Найдет слова длиннее 5 символов
console.log( 'Words 5 chars or longer: ', text.match(/\b\w{5,}\b/g) );
// Найдет слова точно 6 символов длиной
console.log( 'Words exactly 6 chars long: ', text.match(/\b\w{6}\b/g) );
Валидация целых строк
В JavaScript такие выражения можно использовать для проверки пользовательского ввода из текстовых полей. Для валидации строк используется обычное регулярное выражение, привязанное к началу и концу фрагмента текста, использующее для этого выражения ^ (начало строки) и $ (конец строки). Эти символы гарантируют, что шаблон, который вы пишете, охватывает всю длину текста, а не только соответствует его части.
Кроме того, в этом случае мы используем метод test() объекта regex, который возвращает true или false, при проверке соответствия регулярного выражения строке.
// У нас имеется массив строк, давайте найдем ссылки.
var strings = [
'https://proglib.io/',
'this is not a URL',
'https://google.com/',
'123461',
'https://proglib.io/?s=google',
'http://not a valid url',
'abc http://invalid.url/'
];
var regex = /^https?:\/\/[\w\/?.&-=]+$/;
var urls = [];
for( var i = 0; i < strings.length; i++ ){
if( regex.test(strings[i]) ){
// Валидная ссылка
urls.push(strings[i]);
}
}
console.log('Valid URLs: ', urls);
Поиск и замена
Другой общей задачей, которая облегчается использованием регулярных выражений, является поиск и замена текста.
Набор шаблонов, заключенных в круглые скобки () – это группа. Каждая группа собирает текст, который соответствует шаблонам. Текст, сравниваемый с каждой группой, может быть отмечен позже индексами с префиксом в виде знака доллара (начиная с $1 для первой группы).
// Используем обратные ссылки
// Найдем слова, состоящие только из одинаковых букв
var text = 'Abc ddefg, hijk lllll mnopqr ssss. Tuv wxyyy z.';
var sameLetterRegex = /\b(\w)\1*\b/g;
console.log( text.match(sameLetterRegex) );
// Давайте переделаем "John Smith" в "Smith, John"
// Каждая группа (\w+) совпадает с одним словом. Каждой группе
// присваивается индекс, начинающийся с $1
var name = 'John Smith';
var nameRegex = /(\w+) (\w+)/;
console.log( name.replace(nameRegex, '$2, $1') );
// Или сделаем фамилию с большой буквы
var upcasename = name.replace(nameRegex, function(string, group1, group2){
return group2.toUpperCase() + ', ' + group1;
});
console.log( upcasename );
Дополнительные ресурсы и дальнейшее чтение
Описанные в этой статье примеры помогут в решении 80% проблем, связанных с регулярными выражениями. Для остальных 20% загляните на следующие ресурсы:
RegexOne - интерактивное учебное пособие по регулярным выражениям.
Mozila's JavaScript Regex
Regexr - инструмент для визуальной отладки и тестирования регулярных выражений в браузере.
regular-expressions.info - масса информации и технических деталей о регулярных выражениях.
Комментарии