JavaScript | Квантификаторы | Самая длинная и Самая короткая последовательности сопоставления

JavaScript | Квантификаторы | Самая длинная и Самая короткая последовательности сопоставления

Два производства КВАНТИФИКАТОРОВ

Начнём с того, что по стандарту ECMAScript квантификаторы могут иметь всего 2 (два) производства:

Два производства КВАНТИФИКАТОРА по стандарту ECMAScript
Два производства КВАНТИФИКАТОРА по стандарту ECMAScript

 

  • Производство № 1 — КАНТИФИКАТОР — это префикс квантификатора
  • Производство № 2 — КАНТИФИКАТОР — это префикс квантификатора и знак вопроса (?) справа

 

Видео для понимания

В видео подробно рассмотрен вопрос разницы двух производств квантификаторов

 

В чём разница двух производств?

Производство № 1 позволяет сопоставлять строку до НАХОЖДЕНИЯ САМОГО ДАЛЬНЕГО СИМВОЛА в цепочке повторений, которые отрабатывает стандартный префикс квантификатора.

Производство № 2 позволяет сопоставлять строку до НАХОЖДЕНИЯ САМОГО БЛИЖНЕГО СИМВОЛА в цепочке повторений, которые отрабатывает стандартный префикс квантификатора.

Именно в этом и заключается самое ПОЛЕЗНОЕ и ВАЖНОЕ отличие всех возможных квантификаторов друг от друга.

 

Все виды квантификаторов

Напомню, что всего существует 12 вариантов квантификаторов. Не больше, не меньше. Можно один раз запомнить навсегда. Какие они?

Из производства № 1:

*
+
?
{ DecimalDigits[~Sep] }
{ DecimalDigits[~Sep] , }
{ DecimalDigits[~Sep] , DecimalDigits[~Sep] }

Из производства № 2:

*?
+?
??
{ DecimalDigits[~Sep] }?
{ DecimalDigits[~Sep] , }?
{ DecimalDigits[~Sep] , DecimalDigits[~Sep] }?

 

Примеры работы

Есть строка

let str = 'aaa bbb ccc aaa bbb ccc'

 

Из производства № 1:

/.*b/.exec(str)
['aaa bbb ccc aaa bbb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.+b/.exec(str)
['aaa bbb ccc aaa bbb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.?b/.exec(str)
[' b', index: 3, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.{5}b/.exec(str)
['aaa bb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.{5,}b/.exec(str)
['aaa bbb ccc aaa bbb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.{5,16}b/.exec(str)
['aaa bbb ccc aaa b', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

 

Из производства № 2:

/.*?b/.exec(str)
['aaa b', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.+?b/.exec(str)
['aaa b', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.??b/.exec(str)
[' b', index: 3, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.{5}?b/.exec(str)
['aaa bb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.{5,}?b/.exec(str)
['aaa bb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

/.{5,16}?b/.exec(str)
['aaa bb', index: 0, input: 'aaa bbb ccc aaa bbb ccc', groups: undefined]

 

Реальный пример из жизни

Представьте, что мы хотим вытащить все значения из атрибутов href из строки с HTML -разметкой. Как это сделать при помощи регулярного выражения и квантификатора?

let str = ‘<tr bgcolor=»#eaeaea»> <td><font size=»-1″><a href=»./60/60.html»>60</a></font></td> <td align=»left»><font size=»-1″>Прикладные науки. Общие вопросы</font></td> <td align=»left»><font size=»-1″>8</font></td> </tr> <tr bgcolor=»#eaeaea»> <td><font size=»-1″><a href=»./61/61.html»>61</a></font></td> <td align=»left»><font size=»-1″>Медицина. Охрана здоровья. Пожарное дело</font></td> <td align=»left»><font size=»-1″>13058</font></td> </tr> <tr bgcolor=»#eaeaea»> <td><font size=»-1″><a href=»./62/62.html»>62</a></font></td> <td align=»left»><font size=»-1″>Инженерное дело. Техника в целом</font></td>

Пишем шаблон регулярного выражения:

/ href/

Нужно проговорить несколько нюансов. Наш ориентир это слово ‘href‘, то есть последовательность символов, которая равна ‘href‘. По стандарту HTML перед атрибутом ‘href‘ должен быть как минимум один пробел. Зацепимся за это условие.

Далее. После слова href может быть пробел, а может и не быть вовсе. Такое поведение не нарушает стандарт HTML. В идеальном мире мы хотим увидеть после href символ равенства и двойные кавычки.

/ href="/

Но убогие разработчики могут генерировать разметку вот так:

/ href = "/

или даже так

/ href      =     "/

 

ВНИМАНИЕ!

Тут в игру вступает квантификатор из второго производства, который найдёт самый короткий путь до первой двойной кавычки.

/ href *?= *?"/

Затем нам нужно повторить ситуацию:

/ href *?= *?".*?"/

Так мы получим href и все символы до второй двойной кавычки после него.

 

Чтобы получить само значение между кавычками, нужно просто добавить Спецификатор Группы из Atom, а затем отловить его при помощи Подстановок методом matchAll для экземпляров RegExp.

[.../ href *?= *?"(.*?)"/g[Symbol.matchAll](str)].map(i=>i[1])
Вытащили значения атрибутов href из HTML-разметки при помощи RegExp и JavaScript
Вытащили значения атрибутов href из HTML-разметки при помощи RegExp и JavaScript

 

Информационные ссылки

Стандарт ECMAScripthttps://tc39.es/ecma262/multipage/

Стандарт ECMAScript — Раздел «22.2 RegExp (Regular Expression) Objects» — https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp-regular-expression-objects