Про регулярные выражения важно понять одну вещь: если паттерну соответствует любая часть строки, совпадение засчитывается.
Поэтому паттерн /123/
будет соответствовать любой строке, где есть цифры 1, 2 и 3 — в начале, середине или конце: 123abc
, 123
, 12345
, 01234
, -123
.
Поэтому важно задавать ограничения. Чаще всего паттерну должен удовлетворять текст в начале строки, тогда в начале паттерна ставят "крышку" ^
.
/^123/
будет соответствовать любой строке, которая начинается с 123.
Точно также /123$/
будет соответствовать любой строке, которая заканчивается на 123.
Если бы вы хотели, чтобы строка состояла из #
и четырёх цифр, вам подошёл бы паттерн /^#\d\d\d\d$/
или /^#\d{4}$/
. ^
в начале и $
в конце указывают, что строка должна соответствовать паттерну целиком.
Но в вашем случае ограничения должны быть более тонкими. Паттерну должна удовлетворять часть строки, но есть дополнительное условие: сразу за ним не должно быть цифры. У нас по сути получается два паттерна. Сначала мы находим часть строки, которая соответствует первому паттерну, а потом заглядываем вперёд (look ahead) и убеждаемся, что оставшаяся часть строки соответствует второму.
Второй паттерн надо указать сразу после первого в скобках (?=)
или (?!)
.
/#\d{4}(?!\d)/
означает "после проверки паттерна #\d{4}
заглянуть дальше и убедиться, что там не цифра". Это — негативная проверка.
(?=)
это позитивная проверка, то есть мы убеждается, что за первым паттерном точно следует второй. Утверждение не цифра мы можем выразить и так, но выражение будет сложнее /#\d{4}(?=[^\d])/
. Мы помним, что [^\d]
соответствует любому символу, который не является цифрой.