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

Из-за этого мы говорим, что операторы повторения (>+, >*, >?, and >{}) жадные, то есть они сначала захватывают, сколько могут, а потом идут назад. Если вы поместите вопрос после такого оператора (>+?, >*?, >??, >{}?), они превратятся в нежадных, и начнут находить самые маленькие из возможных вхождений.

И это то, что нам нужно. Заставив звёздочку находить совпадения в минимально возможном количестве символов строчки, мы поглощаем только один блок комментариев, и не более того.

>function stripComments(code) {

>  return code.replace(/\/\/.*|\/\*[^]*?\*\//g, "");

>}

>console.log(stripComments("1 /* a */+/* b */ 1"));

>// → 1 + 1

Множество ошибок возникает при использовании жадных операторов вместо нежадных. При использовании оператора повтора сначала всегда рассматривайте вариант нежадного оператора.

Динамическое создание объектов RegExp

В некоторых случаях точный шаблон неизвестен во время написания кода. Например, вам надо будет искать имя пользователя в тексте, и заключать его в подчёркивания. Так как вы узнаете имя только после запуска программы, вы не можете использовать запись со слэшами.

Но вы можете построить строку и использовать конструктор >RegExp. Вот пример:

>var name = "гарри";

>var text = "А у Гарри на лбу шрам.";

>var regexp = new RegExp("\\b(" + name + ")\\b", "gi");

>console.log(text.replace(regexp, "_$1_"));

>// → А у _Гарри_ на лбу шрам.

При создании границ слова приходится использовать двойные слэши, потому что мы пишем их в нормальной строке, а не в регулярке с прямыми слэшами. Второй аргумент для >RegExp содержит опции для регулярок – в нашем случае >“gi”, т. е. глобальный и регистронезависимый.

Но что, если имя будет >"dea+hl[]rd" (если наш пользователь – кульхацкер)? В результате мы получим бессмысленную регулярку, которая не найдёт в строке совпадений.

Мы можем добавить обратных слэшей перед любым символом, который нам не нравится. Мы не можем добавлять обратные слэши перед буквами, потому что >\b или >\n – это спецсимволы. Но добавлять слэши перед любыми не алфавитно-цифровыми символами можно без проблем.

>var name = "dea+hl[]rd";

>var text = "Этот dea+hl[]rd всех достал.";

>var escaped = name.replace(/[^\w\s]/g, "\\$&");

>var regexp = new RegExp("\\b(" + escaped + ")\\b", "gi");

>console.log(text.replace(regexp, "_$1_"));

>// → Этот _dea+hl[]rd_ всех достал.

Метод search

Метод >indexOf нельзя использовать с регулярками. Зато есть метод >search, который как раз ожидает регулярку. Как и >indexOf, он возвращает индекс первого вхождения, или -1, если его не случилось.

>console.log(" word".search(/\S/));