Основы регулярных выражений в javascript

Разбиение строки на подстроки

Метод split()
позволяет разбить строку на подстроки по определенному разделителю. Разделитель
– это какой-нибудь символ или набор символов (передается в качестве параметра).
Например, разобьем текст на отдельные слова (учитывая, что слова разделены
пробелом):

String text = "Я люблю язык Java!";
String words = text.split(" ");
 
for(String word  words)
    System.out.println(word);

Видео по теме

#1 Установка пакетов и первый запуск программы

#2 Структура программы, переменные, константы, оператор присваивания

#3 Консольный ввод/вывод, импорт пакетов

#4 Арифметические операции

#5 Условные операторы if и switch

#6 Операторы циклов while, for, do while

#7 Массивы, обработка элементов массива

#8 (часть 1) Строки в Java, методы класса String

#8 (часть 2) Строки — классы StringBuffer и StringBuider

#9 Битовые операции И, ИЛИ, НЕ, XOR

#10 Методы, их перегрузка и рекурсия

str.matchAll(regexp)

Новая возможность

Эта возможность была добавлена в язык недавно.
В старых браузерах может понадобиться полифил.

Метод – «новый, улучшенный» вариант метода .

Он используется, в первую очередь, для поиска всех совпадений вместе со скобочными группами.

У него 3 отличия от :

  1. Он возвращает не массив, а перебираемый объект с результатами, обычный массив можно сделать при помощи .
  2. Каждое совпадение возвращается в виде массива со скобочными группами (как без флага ).
  3. Если совпадений нет, то возвращается не , а пустой перебираемый объект.

Пример использования:

При переборе результатов в цикле вызов , разумеется, не нужен.

Классы символов

В то время как символьные литералы работают, если вы знаете точный шаблон, символьные классы позволяют вам быть менее конкретными.

Группы символов

позволяет вам сопоставить любое количество символов на одной позиции, в то время как соответствует только символам, НЕ входящим в группу.

Следующее выражение вернёт истину, если шаблон найдёт big, bog или bug.

'big' -match 'bg'

Если ваш список символов для сопоставления включает символ дефиса (-), он должен быть в начале или в конце списка, чтобы отличить его от выражения диапазона символов.

Диапазоны символов

В качестве части шаблона также можно указать диапазон набора символов. Символы могут быть буквенными , числовыми или даже основанными на ASCII (все печатные символы).

Выражение вернёт истину, поскольку шаблон соответствует любому двухзначному числу:

42 -match ''

Числа

У некоторых часто используемых диапазонов есть свои собственные обозначения. Обозначение \d соответствует любой десятичной цифре. И наоборот, \D соответствует любой не десятичной цифре.

Это выражение соответствует именам в диапазоне Server-01 — Server-99, поэтому выражение вернёт истину:

'Server-01' -match 'Server-\d\d'

Следующая запись по значению идентична предыдущей:

'Server-01' -match 'Server-'

Обозначение слова

Класс символов \w обозначает слово , то есть это любая последовательность из букв, цифр и нижнего подчёркивания. Для обозначения не-слова используется \W.

Это выражение вернёт истину. Этот шаблон (регулярное выражение) совпадёт с первым символом «B»:

'Book' -match '\w'

Найденные совпадения сохраняются в переменную $Matches, поэтому вы можете проверять, какая именно строка совпала с регулярным выражением:

'Server-01' -match '\w'
$Matches
'Server-01' -match '\W'
$Matches

Подстановочные знаки

Точка (.) – это подстановочный знак в регулярных выражениях. Она будет соответствовать любому одному символу, кроме новой строки (\n).

Это выражение возвращает истину. Шаблон соответствует любым 4 символам, кроме символа новой строки.

'a1\ ' -match '....'

Белый пробел

Белый пробел (соответствует пробелу, вертикальному и горизонтальному Tab, символу Newline и некоторым другим аналогичным символам) обозначается как \s. Любой непробельный символ обозначается как \S. Также можно использовать буквальные символы пробела ‘ ‘.

Это выражение возвращает истину. В шаблоне используются оба метода для сопоставления пробела (условное обозначение класса символов и буквальный пробел):

' - ' -match '\s- '

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

в следующем примере кода показано, как можно использовать платформа .NET Framework поддержки регулярных выражений для изменения порядка или переформатирования данных. В следующем примере кода используются классы Regex и Match для извлечения первых и последних имен из строки и последующего вывода этих элементов имени в обратном порядке.

Класс Regex используется для создания регулярного выражения, описывающего текущий формат данных. Предполагается, что два имени разделяются запятыми и могут использовать любой пробел вокруг запятой. Затем метод Match используется для анализа каждой строки. В случае успеха первые и последние имена извлекаются из объекта Match и отображаются.

str.match(regexp)

Метод ищет совпадения с в строке .

У него есть три режима работы:

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

  2. Если у регулярного выражения есть флаг , то он возвращает массив всех совпадений, без скобочных групп и других деталей.

  3. Если совпадений нет, то, вне зависимости от наличия флага , возвращается .

    Это очень важный нюанс. При отсутствии совпадений возвращается не пустой массив, а именно . Если об этом забыть, можно легко допустить ошибку, например:

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

Основы

Чаще всего мы ищем данные по его полному или частичному совпадению. Например нам нужно найти элемент массива в котором есть число 1, тогда мы выполним следующее действие:

Сам параметр Like не относится к регулярным выражениям, но он позволяет искать по маскам (wildcard). Когда мы указываем знак звездочки ‘*’ мы говорим, что в этой части может быть неограниченное количество символов. В нашем случае ‘*1*’ говорит, что слева и справа может находится неограниченное количество символов. Есть еще один параметр в виде знака вопроса ‘?’, который указывает на присутствие одного символа.

Использование этих параметров немного усложнит поиск дат в таком массиве:

Можно усложнить поиск используя маски и добавив множество условий, но если таких записей будет тысячи у нас наверняка будут ошибки. Для обхода таких ситуаций нужно использовать регулярные выражения. Их особенность в том, что мы можем искать последовательности из разных символов. У нас доступно больше специальных символов чем в масках:

  • \d — обозначает число от 0 до 9;
  • \w — буква или число от ‘a’ до ‘z’, от ‘A’ до ‘Z’, от 0 до 9 и нижнее подчеркивание ‘_’;
  • \s — пробел, который так же можно указывать как обычный ‘ ‘;
  • . — обозначает любой символ кроме новой строки;
  • * — повторение предыдущего элемента ноль или множество раз;
  • + — повторение предыдущего символа 1 или более раз;
  • () — выражение (группировка);
  • ? — ищет наличие или отсутствие предыдущего символа;
  • \ — экранирует любой специальны символ (метасимвол).

Использование любых символов кроме специальных будет соответствовать точному совпадению. Например поиск строк похожих на даты будет выглядеть так:

Далее рассмотрим с помощью каких инструментов и как можно применять regex.

Вам так же будет интересно:

Получения результата соответствия по шаблону и группировка

Если вы хотите немного увеличить читаемость шаблона регулярных выражений, то можно использовать группы, которые обозначаются круглыми скобками ().

По шаблону ниже мы ищем значения, где есть от 1 до 3 цифр, пробел после которого идет слово ‘rub’:

Если не использовать группировку, то все тоже будет работать, но читаться будет тяжелее:

Захват с $Matches

При использовании групп у нас появляется специальная переменная $Matches, которая хранит найденные по шаблонам результаты:

Первая группы, которая попадает в $Matches — это весь шаблон от кавычки до кавычки. Далее идут совпадения, которые находятся в круглых скобках (). Проблема в том, что в $Matches появляется только первый найденный результат и из-за этого значение в ‘200 руб’ у нас не отображается. О том как это исправить будет рассмотрено в следующей главе.

Сам $Matches имеет тип hashtable, который позволяет получать значения по именам:

Мы можем присвоить свои имена указав свои со следующим синтаксисом:

  • (?<Имя>шаблон)
  • (?Имяшаблон)

Если вы планируете использовать вариант с кавычками — не забывайте использовать иные для экранирования всего шаблона:

Когда нужно исключить группу для сохранения в $Matches, можно использовать ‘?:’ :

Как видно у нас сохранилась только одна общая группа (между кавычками).

Захват всех результатов с Select-String

Для получения всех результатов по шаблону нужно использовать команду Select-String. Продолжая прошлый пример все значения можно увидеть так:

Конечно можно использовать конвейер и обращаться к значениям напрямую:

 

Границы

Java Regex API также может соответствовать границам в строке, а именно началом или концом строки, началом слова и т. д. API Java Regex поддерживает следующие границы:

Символ Описание
^ Начало строки
$ Конец строки
\b Граница слова (где слово начинается или заканчивается, например, пробел, табуляция и т. д.).
\B Несловесная граница
\A Начало ввода.
\G Конец предыдущего совпадения
\Z Конец ввода, кроме конечного объекта (если есть)
\z

Начало строки

Соответствие границ ^ соответствует началу строки в соответствии со спецификацией API Java. Например, следующий пример получает только одно совпадение с индексом 0:

String text = "Line 1\nLine2\nLine3";

Pattern pattern = Pattern.compile("^");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

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

Начало соответствия строки / строки часто используется в сочетании с другими символами, чтобы проверить, начинается ли строка с определенной подстроки. Например, этот пример проверяет, начинается ли строка ввода с подстроки http: //:

String text = "http://jenkov.com";

Pattern pattern = Pattern.compile("^http://");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

В этом примере найдено одно совпадение подстроки http: // из индекса 0 в индекс 7 во входном потоке. Даже если бы входная строка содержала больше экземпляров подстроки http: //, они не соответствовали бы этому регулярному выражению, так как оно начиналось с символа ^.

Конец строки

Соответствие $ соответствует концу строки в соответствии со спецификацией Java. На практике, однако, похоже, что он соответствует только концу входной строки.

Соответствие начала строки часто используется в сочетании с другими символами, чаще всего для проверки, заканчивается ли строка определенной подстрокой:

String text = "http://jenkov.com";

Pattern pattern = Pattern.compile(".com$");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

В этом примере будет найдено одно совпадение в конце входной строки.

Объединение строк

Для соединения строк можно использовать
операцию сложения («+»):

String str1 = "Java";
String str2 = "Hello";
String str3 = str1 + " " + str2;
 
System.out.println(str3); // Hello Java

При этом если в операции сложения строк
используется не строковый объект, например, число, то этот объект преобразуется
к строке:

String str4 = "Год " + 2015;

Еще один метод объединения — метод join() позволяет
объединить строки с учетом разделителя. Например, две строки

String str1 = "Java";
String str2 = "Hello";

будут сливаться в одно слово «HelloJava», если их
объединить с помощью оператора +:

String str3 = str1 + str2;

но если мы хотим, чтобы две подстроки при
соединении были разделены пробелом, то можно воспользоваться методом join() следующим
образом:

String str3 = String.join(" ", str2, str1); // Hello Java

В общем случае вместо пробела здесь
можно ставить любой разделитель в виде строки.

Обратите внимание, что каждый раз при
объединении строк мы получали новую строку как результат объединения

Якоря (анкоры)

Якоря указывают на начало и конец строки.

Два обычно используемых якоря — это «^» и «$.» Каретка (^) соответствует началу строки, а знак доллара ($) соответствует концу строки. Якоря позволяют сопоставить текст в определённой позиции, а также отбросить ненужные символы.

Шаблон в следующем примере предполагает, что за буквой h будет стоять конец слова. Это выражение вернёт ЛОЖЬ.

'fishing' -match '^fish$'

При определении регулярного выражения, содержащего привязку $, обязательно заключите регулярное выражение в одинарные кавычки (‘) вместо двойных кавычек («), иначе PowerShell будет трактовать выражение как переменную.

При использовании якорей в PowerShell вы должны понимать разницу между параметрами регулярных выражений SINGLELINE и MULTILINE.

  • MULTILINE: в многострочном режиме символы ^ и $ должны совпадать с началом и концом каждой СТРОКИ, а не с началом и концом входной строки.
  • SINGLELINE: однострочный режим обрабатывает входную строку как ЕДИНУЮ СТРОКУ. Это заставляет символ точки (.) соответствия каждому символу (включая символы новой строки) вместо поведения по умолчанию, которое заключается в следующем: точка соответствует любому символу, ЗА ИСКЛЮЧЕНИЕМ новой строки \n.

Java Regex Core Classes

Состоит из двух основных классов:

  • Шаблон (java.util.regex.Pattern)
  • Соответствия (java.util.regex.Matcher)

Класс Pattern используется для создания шаблонов. Шаблон – это предварительно скомпилированное регулярное выражение в форме объекта (как экземпляр шаблона), способное сопоставляться с текстом.

Класс Matcher используется для сопоставления заданного экземпляра Pattern с текстом несколько раз. Другими словами, искать несколько вхождений в тексте. Matcher скажет вам, где в тексте (индекс символа) он нашел вхождения. Вы можете получить экземпляр Matcher из экземпляра Pattern.

2 ответа

Лучший ответ

На самом деле вам нужно, чтобы был допустимым «числовым символом», но только в начале любого заданного числового блока.

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

Но если бы вы пошли по положительному пути (напишите регулярное выражение, описывающее число ), это было бы тривиально: прекрасно описывает его: необязательный знак минус, за которым следует 1 или более цифр . Достаточно просто. Это даже «сработает», если вы введете «aa —- 5», у которого есть одна совпадающая последовательность (-5).

Так что … сделай это тогда. Вы злоупотребляете здесь . Не злоупотребляйте системами, все идет плохо, если вы немного усложняете их.

Здесь используются несколько приемов:

находит следующую подпоследовательность во входной строке, которая соответствует предоставленному регулярному выражению. По умолчанию регулярные выражения являются «жадными». Это означает, что строку «1234» можно одинаково юридически интерпретировать многими способами: Это один элемент (1234)? В конце концов, просто «1» также соответствует «-? \ D +». «Жадный» означает, что регулярные выражения будут соответствовать самой длинной возможной последовательности. Несомненно, это именно то, что вам нужно.
дает вам совпадение. 0 — это особая группа, включающая всю найденную последовательность

Если вы используете круглые скобки в регулярных выражениях, вы создаете группы, и вы тоже можете их получить, например если вы хотите исключить знак минус, вы могли бы сделать — обратите внимание на круглые скобки. Теперь вы можете делать

Обратите внимание: если у вас должен быть , преобразование списка целых чисел в требует цикла. не может этого сделать ( не является , но пока еще является незаконным java).

rzwitserloot
27 Окт 2021 в 00:52

Это однострочный: разделите начальные и конечные нецифровые цифры, затем разделите на нецифровые / минусовые, конвертируйте в , а затем соберите в массив:

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

Bohemian
27 Окт 2021 в 01:59

Поиск совпадений: метод exec

Метод возвращает массив и ставит свойства регулярного выражения.
Если совпадений нет, то возвращается null.

Например,

// Найти одну d, за которой следует 1 или более b, за которыми одна d
// Запомнить найденные b и следующую за ними d
// Регистронезависимый поиск
var myRe = /d(b+)(d)/ig;
var myArray = myRe.exec("cdbBdbsbz");

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

Объект Свойство/Индекс Описания Пример
Содержимое .
Индекс совпадения (от 0)
Исходная строка.
Последние совпавшие символы
Совпадения во вложенных скобках, если есть. Число вложенных скобок не ограничено.
Индекс, с которого начинать следующий поиск.
Показывает, что был включен регистронезависимый поиск, флаг «».
Показывает, что был включен флаг «» поиска совпадений.
Показывает, был ли включен флаг многострочного поиска «».
Текст паттерна.

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

var myRe = /ab*/g;
var str = "abbcdefabh";
while ((myArray = myRe.exec(str)) != null) {
	var msg = "Found " + myArray + ".  ";
	msg += "Next match starts at " + myRe.lastIndex;
	print(msg);
}

Этот скрипт выведет следующий текст:

Found abb. Next match starts at 3
Found ab. Next match starts at 9

В следующем примере функция выполняет поиск по input. Затем делается цикл по массиву, чтобы посмотреть, есть ли другие имена.

Предполагается, что все зарегистрированные имена находятся в массиве А:

var A = ;

function lookup(input)
{
  var firstName = /\w+/i.exec(input);
  if (!firstName)
  {
    print(input + " isn't a name!");
    return;
  }

  var count = 0;
  for (var i = 0; i < A.length; i++)
  {
    if (firstName.toLowerCase() == A.toLowerCase())
      count++;
  }
  var midstring = (count == 1) ? " other has " : " others have ";
  print("Thanks, " + count + midstring + "the same name!")
}

Статичные регэкспы

В некоторых реализациях javascript регэкспы, заданные коротким синтаксисом /…/ — статичны. То есть, такой объект создается один раз в некоторых реализациях JS, например в Firefox. В Chrome все ок.

function f() {
  // при многократных заходах в функцию объект один и тот же
  var re = /lalala/     
}

По стандарту эта возможность разрешена ES3, но запрещена ES5.

Из-за того, что при глобальном поиске меняется, а сам объект регэкспа статичен, первый поиск увеличивает , а последующие — продолжают искать со старого , т.е. могут возвращать не все результаты.

При поиске всех совпадений в цикле проблем не возникает, т.к. последняя итерация (неудачная) обнуляет .

Пример Pattern

Вот простой пример, чтобы проверить, содержит ли текст подстроку http: //:

String text    =
        "This is the text to be searched " +
        "for occurrences of the http:// pattern.";

String regex = ".*http://.*";

boolean matches = Pattern.matches(regex, text);

System.out.println("matches = " + matches);

Текстовая переменная содержит текст для проверки с помощью регулярного выражения.

Переменная pattern содержит выражение в виде String. Оно соответствует всем текстам, содержащим один или несколько символов (. *), за которыми следует текст http: //, а за ним следует один или несколько символов (. *).

В третьей строке используется статический метод Pattern.matches(), чтобы проверить, соответствует ли шаблон тексту. Если да, то Pattern.matches() возвращает true. Если нет, false.

В этом примере фактически не проверяется, является ли найденная строка http: // частью действительного URL с именем домена и суффиксом (.com, .net и т. д.).

Использование регулярных выражений для извлечения полей данных

В следующем примере кода показано использование регулярных выражений для извлечения данных из форматированной строки. В следующем примере кода класс Regex используется для указания шаблона, соответствующего адресу электронной почты. Этот Паттер включает идентификаторы полей, которые можно использовать для извлечения частей имени пользователя и узла каждого адреса электронной почты. Класс Match используется для выполнения фактического сопоставления шаблонов. Если указан допустимый адрес электронной почты, имя пользователя и имена узлов извлекаются и отображаются.

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: