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

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2023

Просмотров: 23

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Регулярные выражения в 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));

}