Откаты случаются при использовании операторов повторения, таких, как >+
и >*
. Если вы ищете >/^.*x/
в строке >"abcxe"
, часть регулярки >.*
попробует поглотить всю строчку. Алгоритм затем сообразит, что ему нужен ещё и >“x”
. Так как никакого >“x”
после конца строки нет, алгоритм попробует поискать совпадение, откатившись на один символ. После >abcx
тоже нет >x
, тогда он снова откатывается, уже к подстроке >abc
. И после строчки он находит >x
и докладывает об успешном совпадении, на позициях с 0 по 4.
Можно написать регулярку, которая приведёт ко множественным откатам. Такая проблема возникает, когда шаблон может совпасть с входными данными множеством разных способов. Например, если мы ошибёмся при написании регулярки для двоичных чисел, мы можем случайно написать что-то вроде >/([01]+)+b/
.
Если алгоритм будет искать такой шаблон в длинной строке из нолей и единиц, не содержащей в конце “b”, он сначала пройдёт по внутренней петле, пока у него не кончатся цифры. Тогда он заметит, что в конце нет “b”, сделает откат на одну позицию, пройдёт по внешней петле, опять сдастся, попытается откатиться на ещё одну позицию по внутренней петле… И будет дальше искать таким образом, задействуя обе петли. То есть, количество работы с каждым символом строки будет удваиваться. Даже для нескольких десятков символов поиск совпадения займёт очень долгое время.
У строк есть метод >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
в строчке на замену ссылаются на группы символов, заключённые в скобки.