Главная страница

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


Скачать 31.42 Kb.
НазваниеОбъект RegExp Объект типа RegExp, или, короче, регулярное выражение, можно создать двумя путями
Дата27.04.2023
Размер31.42 Kb.
Формат файлаdocx
Имя файлаРегулярные выражения.docx
ТипДокументы
#1093630

Регулярные выражения в javascript имеют особую краткую форму и стандартный PCRE-синтаксис. Работают они через специальный объект RegExp. Кроме того, у строк есть свои методы search,match,replace, но чтобы их понять - разберем сначала RegExp.

Объект RegExp

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

/pattern/флаги

new RegExp("pattern"[, флаги])

 

 pattern - регулярное выражение для поиска (о замене - позже), а флаги - строка из любой комбинации символов g(глобальный поиск), i(регистр неважен) и Ш(многострочный поиск).

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

var reg = /ab+c/i

var reg = new RegExp("ab+c", "i")

 

При втором вызове - т.к регулярное выражение в кавычках, то нужно дублировать \// эквивалентны

re = new RegExp("\\w+")

re = /\w+/

 

При поиске можно использовать большинство возможностей современного PCRE-синтаксиса.

 

 Спецсимволы в регулярном выражении

 

Символ

Значение

\

Для обычных символов - делает их специальными. Например, выражение /s/ ищет просто символ 's'. А если поставить \ перед s, то /\s/ уже обозначает пробельный символ.И наоборот, если символ специальный, например *, то \ сделает его просто обычным символом "звездочка". Например, /a*/ ищет 0 или больше подряд идущих символов 'a'. Чтобы найти а со звездочкой 'a*' - поставим \ перед спец. символом: /a\*/.

^

Обозначает начало входных данных. Если установлен флаг многострочного поиска ("m"), то также сработает при начале новой строки.Например, /^A/ не найдет 'A' в "an A", но найдет первое 'A' в "An A."

$

Обозначает конец входных данных. Если установлен флаг многострочного поиска, то также сработает в конце строки.Например, /t$/ не найдет 't' в "eater", но найдет - в "eat".

*

Обозначает повторение 0 или более раз. Например, /bo*/ найдет 'boooo' в "A ghost booooed" и 'b' в "A bird warbled", но ничего не найдет в "A goat grunted".

+

Обозначает повторение 1 или более раз. Эквивалентно {1,}. Например, /a+/ найдет 'a' в "candy" и все 'a' в "caaaaaaandy".

?

Обозначает, что элемент может как присутствовать, так и отсутствовать. Например, /e?le?/ найдет 'el' в "angel" и 'le' в "angle."Если используется сразу после одного из квантификаторов *, +, ?, или {}, то задает "нежадный" поиск (повторение минимально возможное количество раз, до ближайшего следующего элемента паттерна), в противоположность "жадному" режиму по умолчанию, при котором количество повторений максимально, даже если следующий элемент паттерна тоже подходит.Кроме того, ? используется в предпросмотре, который описан в таблице под (?=), (?!), и (?: ).

.

(Десятичная точка) обозначает любой символ, кроме перевода строки: \n \r \u2028 or \u2029. (можно использовать [\s\S] для поиска любого символа, включая переводы строк). Например, /.n/ найдет 'an' и 'on' в "nay, an apple is on the tree", но не 'nay'.

(x)

Находит x и запоминает. Это называется "запоминающие скобки". Например, /(foo)/ найдет и запомнит 'foo' в "foo bar." Найденная подстрока хранится в массиве-результате поиска или в предопределенных свойствах объекта RegExp: $1, ..., $9.Кроме того, скобки объединяют то, что в них находится, в единый элемент паттерна. Например, (abc)* - повторение abc 0 и более раз.

(?:x)

Находит x, но не запоминает найденное. Это называется "незапоминающие скобки". Найденная подстрока не сохраняется в массиве результатов и свойствах RegExp.Как и все скобки, объединяют находящееся в них в единый подпаттерн.

x(?=y)

Находит x, только если за x следует y. Например, /Jack(?=Sprat)/ найдет 'Jack', только если за ним следует 'Sprat'. /Jack(?=Sprat|Frost)/ найдет 'Jack', только если за ним следует 'Sprat' или 'Frost'. Однако, ни 'Sprat' ни 'Frost' не войдут в результат поиска.

x(?!y)

Находит x, только если за x не следует y. Например, /\d+(?!\.)/ найдет число, только если за ним не следует десятичная точка. /\d+(?!\.)/.exec("3.141") найдет 141, но не 3.141.

x|y

Находит x или y. Например, /green|red/ найдет 'green' в "green apple" и 'red' в "red apple."

{n}

Где n - положительное целое число. Находит ровно n повторений предшествующего элемента. Например, /a{2}/ не найдет 'a' в "candy," но найдет оба a в "caandy," и первые два a в "caaandy."

{n,}

Где n - положительное целое число. Находит n и более повторений элемента. Например, /a{2,} не найдет 'a' в "candy", но найдет все 'a' в "caandy" и в "caaaaaaandy."

{n,m}

Где n и m - положительные целые числа. Находят от n до m повторений элемента.

[xyz]

Набор символов. Находит любой из перечисленных символов. Вы можете указать промежуток, используя тире. Например, [abcd] - то же самое, что [a-d]. Найдет 'b' в "brisket", а также 'a' и 'c' в "ache".

[^xyz]

Любой символ, кроме указанных в наборе. Вы также можете указать промежуток. Например, [^abc] - то же самое, что [^a-c]. Найдет 'r' в "brisket" и 'h' в "chop."

[\b]

Находит символ backspace. (Не путать с \b.)

\b

Находит границу слов (латинских), например пробел. (Не путать с [\b]). Например, /\bn\w/ найдет 'no' в "noonday"; /\wy\b/ найдет 'ly' в "possibly yesterday."

\B

Обозначает не границу слов. Например, /\w\Bn/ найдет 'on' в "noonday", а /y\B\w/ найдет 'ye' в "possibly yesterday."

\cX

Где X - буква от A до Z. Обозначает контрольный символ в строке. Например, /\cM/ обозначает символ Ctrl-M.

\d

находит цифру из любого алфавита. Используйте [0-9], чтобы найти только обычные цифры. Например, /\d/ или /[0-9]/ найдет '2' в "B2 is the suite number."

\D

Найдет нецифровой символ (все алфавиты). [^0-9] - эквивалент для обычных цифр. Например, /\D/ или /[^0-9]/ найдет 'B' в "B2 is the suite number."

\f,\r,\n

Соответствующие спецсимволы form-feed, line-feed, перевод строки.

\s

Найдет любой пробельный символ, включая пробел, табуляцию, переводы строки и другие юникодные пробельные символы. Например, /\s\w*/ найдет ' bar' в "foo bar."

\S

Найдет любой символ, кроме пробельного. Например, /\S\w*/ найдет 'foo' в "foo bar."

\t

Символ табуляции.

\v

Символ вертикальной табуляции.

\w

Найдет любой словесный (латинский алфавит) символ, включая буквы, цифры и знак подчеркивания. Эквивалентно [A-Za-z0-9_]. Например, /\w/ найдет 'a' в "apple," '5' в "$5.28," и '3' в "3D."

\W

Найдет любой не-(лат.)словесный символ. Эквивалентно [^A-Za-z0-9_]. Например, /\W/ и /[^$A-Za-z0-9_]/ одинаково найдут '%' в "50%."

\n

где n - целое число. Обратная ссылка на n-ю запомненную скобками подстроку. Например, /apple(,)\sorange\1/ найдет 'apple, orange,' в "apple, orange, cherry, peach.". За таблицей есть более полный пример.

\0

Найдет символ NUL. Не добавляйте в конец другие цифры.

\xhh

Найдет символ с кодом hh (2 шестнадцатиричных цифры)

\uhhhh

Найдет символ с кодом hhhh (4 шестнадцатиричных цифры).

Пример 1:

 

Задача: разбить строку, содержащую IP адрес ipv4 на компоненты

Вход: текстовая строка четыре числа разделённые точкой

Выход: четыре числа компоненты адреса

 

 var myRe = /(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)/;

          if (myRe.test('192.168.25.40'))

          {

            var ar = myRe.exec('192.168.25.40'); 

            alert(ar[1] + '.' + ar[2] + '.' + ar[3] + '.' + ar[4]);

 } 

 

Пример 2

 

Выделение IP-адресов в тексте (IPv4)

  /*

  Ниже приведен пример регулярного выражения с пояснениями

  (                           # начало группы

    (?=\d+\.\d+\.\d+\.\d+)     # основная часть выражения, требующая формата: число.число.число.число

    (?:                         # начало незахватывающей группы (число 0-255 + опциональная точка)

      (?:                         # начало незахватывающей группы (число 0-255)

        25[0-5]                     # 250-255

        |                           # или

        2[0-4][0-9]                 # 200-249

        |                           # или

        1[0-9]{2}                   # 100-199

        |                           # или

        [1-9][0-9]                  # 10-99

        |                           # или

        [0-9]                       # 0-9

      )                           # конец незахватывающей группы

      \.?                         # опциональная точка

    ){4}                        # конец незахватывающей группы (число + опциональная точка), повторяется четыре раза

  )                           # конец группы  

  */

  var reg = /((?=\d+\.\d+\.\d+\.\d+)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4})/g;

  var sourceStr = "Это строка, которая содержит IP-адрес: '192.68.35.35',"

    + "'0.0.0.0','255.0.0.0','192.168.1.0','192.168.0.1',"

    + "'255.255.255.0','1.1.1.1','255.255.255.255','249.249.249.249',"

    + "'200.200.200.200','199.199.199.199'";

  var ips = null;

  while ((ips = reg.exec(sourceStr)) != null)

    Log.writeLine(ips[0]);

 

Пример 3

 

Выделение IP-адресов в тексте (IPv6)

  

  /*

    Распознавание IP-адреса в формате IPv6:

    2a03:1800:1:4:217:31ff:feb4:8d55

    

  */

var reg = /([0-9a-f]|:){1,4}(:([0-9a-f]{0,4})*){1,7}$/ig;

var sourceStr = "Эта строка содержит адрес в формате IPv6: 2a03:1800:1:4:217:31ff:feb4:8d55";

var dest = sourceStr.match(reg);

if (dest)

  alert(dest[0]);

 

Пример 4:

 

Задача: замена переводов строки на пробелы

Вход: произвольная текстовая строка (например из базы) в которой могут быть пробелы

Выход: та же строка где символы перевода строк (\n\r или одиночный \n) заменяются на пробел

 

       var myRe = /(\n(\r)?)/g;

 var str = 'строка1 \n строка2 \n\r строка3 \n\r';

          if (myRe.test(str))

          {

            var result = str.replace(myRe, ' ');

            alert(result);

          }

 

Пример 5:

 

Задача: разбор имени, фамилии и отчества

Вход: строка содержащая имя фимилию и отчество

Выход: три строки, содержащие имя. фамилию и отчество

 

 var str = 'Иван Иванов Иванович';

 var myRe = /([А-Яа-я]+)\s([А-Яа-я]+)\s([А-Яа-я]+)/;

          if (myRe.test(str))

          {

            var ar = myRe.exec(str);

            alert('Имя: ' + ar[1] + ' Фамилия: ' + ar[2] + ' Отчество: ' + ar[3]);

          }

 

Пример 6

 

Замена неправильных символов в имени файла

 

  /*

    Список некорректных символов для имени файла:

    "#", "%", "&", "{", "}", "\", "<", ">", 

    "*", "?", "/", "s", "$", "!", ":", "@", 

    "+", "|", "="

  */

  var reg = /[\#\%\&\{\}\\\<\>\*\?\/\s\$\!\:\@\+\|\=]/g;

  var badFileName = "!123 %%#{}|\/?*.txt"; 

  var goodFileName = badFileName.replace(reg, "_");

  alert(goodFileName);

 

Пример 7

 

Замена всех символов, кроме разрешенных

 

  /*

    Список разрешенных символов:

    "a", "s", "D", "e", "c", "v", "b", "n"

  */

  var reg = /[^asDecvbn]/g;

  var badStr = "fdgasyyrDnnb";

  var goodStr = badStr.replace(reg, "");

  alert(goodStr);

 

Пример 8

 

Разбор даты и времени из лога

 

  /*

    Пример данных из Log-файла:

    2016/12/27 11:48:14:527 [7672, 392] INFO  Terminating: TCustomForm.Close{not HasOtherVisibleForms}

    2016/12/27 11:48:14:528 [7672, 392] INFO  Application.LastShowedForm: TNotifyView[]

    2016/12/27 11:48:14:533 [7672,2288] INFO  SendingThread::PING

    2016/12/27 11:48:14:535 [7672,4684] INFO  ReceivingThread::PONG

    2016/12/27 11:48:14:540 [7672, 392] INFO  close [node:19996385127421]

    2016/12/27 11:48:14:656 [7672, 392] INFO  FinalizePhenixKernel

    2016/12/27 11:48:14:767 [7672,4684] INFO  ReceivingThread normal exit

    2016/12/27 11:48:14:797 [7672,2288] INFO  SendingThread normal exit

    2016/12/27 11:48:15:966 [7672, 392] INFO  Конфигурация [70202972297322] не сохранена: нет подключения

    2016/12/27 11:48:15:970 [7672, 392] INFO  main exit

  */

  var regDateTime = /(\d+\/\d+\/\d+\s\d+\:\d+\:\d+)/g;

  var regDate = /(\d+\/\d+\/\d+)/g;

  var regTime = /(\d+\:\d+\:\d+)/g;

  var file = FileSystem.openTextFile("e:/example/log.txt");

  try 

  {

    while (!file.eof) 

    {

      var line = Strings.trimAll(file.readLine());

      if (!line)

        continue;

      var dateTimeStr = line.match(regDateTime);

      if (!dateTimeStr)

        continue;

      var date = dateTimeStr[0].match(regDate)[0].split("/");

      var time = dateTimeStr[0].match(regTime)[0].split(":");

      var year = date[0]; 

      var month = date[1];

      var day = date[2];

      var hour = time[0];

      var minute = time[1];

      var second = time[2]; 

      Log.writeLine("Результат разбора даты");

      Log.writeLine("год: " + year + " месяц: " + month + " день: " + day);

      Log.writeLine("Результат разбора времени");

      Log.writeLine("часы: " + hour + " минуты: " + minute + " секунды: " + second);

    }

  

  finally 

  {

    file.close();

  }

 

Пример 9

 

Замена ',' на ';'

 

  varreg = /\,/g;

  varsourceStr = "Это некоторая строка, содержащая символ ','";

  vardestStr = sourceStr.replace(reg";");

  alert(destStr); 

 

Пример 10

 

Распознавание телефонного номера

 

  varreg = /((8|\+7)[\- ]?)?(\(?\d{3,5}\)?[\- ]?)?[\d\- ]{5,10}/g;

  varsourceStr = "Данная строка содержит несколько номеров в разных форматах: "

    "'+79261234567', "

    "'89261234567', "

    "'79261234567', "

    "'+7 926 123 45 67', "

    "'8(926)123-45-67', "

    "'123-45-67', "

    "'9261234567', "

    "'79261234567', "

    "'(495)1234567', "

    "'(495) 123 45 67', "

    "'89261234567', "

    "'8-926-123-45-67', "

    "'8 927 1234 234', "

    "'8 927 12 12 888', "

    "'8 927 12 555 12', "

    "'+7 (4932) 23-08-64', "

    "'8 927 123 8 123'";

  varphones = null;

  while ((phones = reg.exec(sourceStr)) != null)

    Log.writeLine(phones[0]); 

 

Пример 11

 

   Обработка ошибок phx.err

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

 

  varphxErrStr = 

    "2016/01/20 16:59:36:563 [3204,3976] ERROR v5.2.125/5.2.126 fav: Невозможно перенести узел[70202975761937]  сам в себя"

      "inform.adt.InformException: Невозможно перенести узел[70202975761937]  сам в себя "

      "inform.adt.InformException"

      "        at inform.agent.mtd.nodes.Node.changeParent(Node.java:1268)"

      "        at inform.agent.mtd.nodes.Node.changeParent(Node.java:1294)"

      "        at inform.agent.mtd.nodes.BasicNode.changeParent(BasicNode.java:882)"

      "        at inform.agent.mtd.request.ModifyNode.modifyNode(ModifyNode.java:92)...";

  varreg = /(5\.2\.\d+)\/(5\.2\.\d+)\s([A-z0-9]+)/;

  varres = phxErrStr.match(reg);

  if (res)

  {

    Log.writeLine("Версия клиента: " + res[1]);

    Log.writeLine("Версия сервера: " + res[2]);

    Log.writeLine("Имя пользователя: " + res[3]);

  }

 

Пример 12

 

Применение шаблона ${<выражение JS>}

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

 

functionevaluate(contextevalStr)

{

  with (context)

    returneval(evalStr);

}

 

functionapplyTemplate(templatecontextObject)

{

  returntemplate.replace(/\${([^}]+)}/g, function(_expr) {

      returnevaluate(contextObjectexpr);

  });

}

 

functionjsTemplateRecognition()

{

  /*

    Применение шаблона ${<выражение JS>}

  */

  vartemplate1 = "Фирма '${name}' имеет контактый телефон '${phone}'";

  vartemplate2 = "Наименование предприятия: ${name} \nКонтактный телефон: ${phone}";

  //В данном примере объект record формируется вручную, но на практике может 

  //формироваться на основе данных из таблицы

  varrecord = {};

  record["name"] = "ООО Рога и копыта";

  record["phone"] = "(4932) 12-34-56";

  Log.writeLine(applyTemplate(template1record));

  Log.writeLine(applyTemplate(template2record));

}


написать администратору сайта