renovations
This commit is contained in:
parent
2022aafc13
commit
dceccedb58
60 changed files with 1730 additions and 272 deletions
|
@ -1,13 +1,18 @@
|
|||
# Жадный и ленивый режимы
|
||||
# Жадные и ленивые квантификаторы [todo]
|
||||
|
||||
Теперь время залезть "под капот" регулярных выражений и посмотреть, как происходит поиск.
|
||||
Квантификаторы -- с виду очень простая, но на самом деле очень хитрая штука.
|
||||
|
||||
Необходимо очень хорошо понимать, как именно происходит поиск, если конечно мы хотим искать что-либо сложнее чем <code class="pattern">/\d+/</code>.
|
||||
|
||||
Это понимание необходимо для того, чтобы искать что-либо сложнее чем <code class="pattern">/\d+/</code>.
|
||||
[cut]
|
||||
|
||||
Для примера рассмотрим задачу, которая часто возникает в типографике -- заменить кавычки вида `"..."` на "кавычки-лапки": `«...»`.
|
||||
Для примера рассмотрим задачу, которая часто возникает в типографике -- заменить в тексте кавычки вида `"..."` (их называют "английские кавычки") на "кавычки-ёлочки": `«...»`.
|
||||
|
||||
Шаблон, который мы будем использовать для поиска подстрок в кавычках, будет выглядеть так:
|
||||
Для этого нужно сначала найти все слова в таких кавычках.
|
||||
|
||||
Соотверствующее регулярное выражение может выглядеть так: <code class="pattern">/".+"/g</code>, то есть мы ищем кавычку, после которой один или более произвольный символ, и в конце опять кавычка.
|
||||
|
||||
Однако, если попробовать применить его на практике, даже на таком простом случае...
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -15,38 +20,48 @@ var reg = /".+"/g;
|
|||
|
||||
var str = 'a "witch" and her "broom" is one';
|
||||
|
||||
alert( str.match(reg) );
|
||||
alert( str.match(reg) ); // "witch" and her "broom"
|
||||
```
|
||||
|
||||
Запустите этот пример...
|
||||
...Мы увидим, что оно работает совсем не так, как задумано!
|
||||
|
||||
Упс! Он не работает! Вместо того, чтобы найти два совпадения <code class="match">"witch"</code> и <code class="match">"broom"</code>, он находит одно: <code class="match">"witch" and her "broom"</code>.
|
||||
Вместо того, чтобы найти два совпадения <code class="match">"witch"</code> и <code class="match">"broom"</code>, оно находит одно: <code class="match">"witch" and her "broom"</code>.
|
||||
|
||||
Это как раз тот случай, когда *жадность* -- причина всех зол.
|
||||
|
||||
## Алгоритм поиска
|
||||
## Жадный поиск
|
||||
|
||||
Движок регулярных выражений пытается проверить строку на соответствие шаблону, начиная с самой первой, нулевой позиции. Если не получается, он идёт вперёд и пытается найти с 1й позиции и так далее.
|
||||
Чтобы найти совпадение, движок регулярных выражений обычно использует следующий алгоритм:
|
||||
|
||||
Чтобы сделать происходящее максимально наглядным и понятным, проследим, что именно он делает для паттерна <code class="pattern">".+"</code>.
|
||||
<ul>
|
||||
<li>Для каждой позиции в поисковой строке
|
||||
<ul>
|
||||
<li>Проверить совпадение на данной позиции
|
||||
<ul><li>Посимвольно, с учётом классов и квантификаторов сопоставив с ней регулярное выражение.</li></ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Это общие слова, гораздо понятнее будет, если мы проследим, что именно он делает для регэкспа <code class="pattern">".+"</code>.
|
||||
|
||||
<ol>
|
||||
<li>Первый символ шаблона -- это кавычка <code class="pattern">"</code>.
|
||||
|
||||
Движок регулярных выражений пытается найти её на 0й позиции, но там совсем другой символ, поэтому на 0й позиции соответствия явно нет.
|
||||
Движок регулярных выражений пытается сопоставить её на 0й позиции в строке, но символ `a`, поэтому на 0й позиции соответствия явно нет.
|
||||
|
||||
Далее он переходит 1ю, 2ю позицию в исходной строке и, наконец, обнаруживает кавычку на 3й позиции:
|
||||
<img src="witch_greedy1.png">
|
||||
<img src="witch_greedy1.svg">
|
||||
</li>
|
||||
<li>Кавычка найдена, далее движок проверяет, есть ли соответствие для остальной части паттерна.
|
||||
|
||||
В данном случае следующий символ паттерна -- `.` (точка). Она обозначает "любой символ", так что следующая буква строки <code class="match">'w'</code> вполне подходит:
|
||||
<img src="witch_greedy2.png">
|
||||
<img src="witch_greedy2.svg">
|
||||
</li>
|
||||
<li>Далее "любой символ" повторяется, так как стоит квантификатор <code class="pattern">.+</code>. Движок регулярных выражений берёт один символ за другим, до тех пор, пока у него это получается.
|
||||
|
||||
В данном случае это означает "до конца строки":
|
||||
<img src="witch_greedy3.png">
|
||||
<img src="witch_greedy3.svg">
|
||||
</li>
|
||||
<li>Итак, текст закончился, движок регулярных выражений больше не может найти "любой символ", он закончил строить соответствие для <code class="pattern">.+</code> и очень рад по этому поводу.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue