Выразительный JavaScript (Хавербеке) - страница 97

Откаты случаются при использовании операторов повторения, таких, как >+ и >*. Если вы ищете >/^.*x/ в строке >"abcxe", часть регулярки >.* попробует поглотить всю строчку. Алгоритм затем сообразит, что ему нужен ещё и >“x”. Так как никакого >“x” после конца строки нет, алгоритм попробует поискать совпадение, откатившись на один символ. После >abcx тоже нет >x, тогда он снова откатывается, уже к подстроке >abc. И после строчки он находит >x и докладывает об успешном совпадении, на позициях с 0 по 4.

Можно написать регулярку, которая приведёт ко множественным откатам. Такая проблема возникает, когда шаблон может совпасть с входными данными множеством разных способов. Например, если мы ошибёмся при написании регулярки для двоичных чисел, мы можем случайно написать что-то вроде >/([01]+)+b/.



Если алгоритм будет искать такой шаблон в длинной строке из нолей и единиц, не содержащей в конце “b”, он сначала пройдёт по внутренней петле, пока у него не кончатся цифры. Тогда он заметит, что в конце нет “b”, сделает откат на одну позицию, пройдёт по внешней петле, опять сдастся, попытается откатиться на ещё одну позицию по внутренней петле… И будет дальше искать таким образом, задействуя обе петли. То есть, количество работы с каждым символом строки будет удваиваться. Даже для нескольких десятков символов поиск совпадения займёт очень долгое время.

Метод replace

У строк есть метод >replace, который может заменять часть строки другой строкой.

>console.log("папа".replace("п", "м"));

>// → мапа

Первый аргумент может быть и регуляркой, в каком случае заменяется первое вхождение регулярки в строке. Когда к регулярке добавляется опция >g (global, всеобщий), заменяются все вхождения, а не только первое.

>console.log("Borobudur".replace(/[ou]/, "a"));

>// → Barobudur

>console.log("Borobudur".replace(/[ou]/g, "a"));

>// → Barabadar

Имело бы смысл передавать опцию «заменить все» через отдельный аргумент, или через отдельный метод типа >replaceAll. Но к сожалению, опция передаётся через саму регулярку.

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

>console.log(

>  "Hopper, Grace\nMcCarthy, John\nRitchie, Dennis"

>    .replace(/([\w ]+), ([\w ]+)/g, "$2 $1"));

>// → Grace Hopper

>//   John McCarthy

>//   Dennis Ritchie

>$1 и >$2 в строчке на замену ссылаются на группы символов, заключённые в скобки.