В чем разница между квадратными скобками и круглыми скобками в регулярном выражении?
Вот регулярное выражение, которое я создал для использования в JavaScript:
var reg_num = /^(7|8|9)\d{9}$/
Вот еще один, предложенный моим членом команды.
var reg_num = /^[7|8|9][\d]{9}$/
Правило состоит в том, чтобы подтвердить номер телефона:
- Это должно быть всего десять чисел.
- Первое число должно быть любым из 7, 8 или 9.
Ответы
Ответ 1
Эти регулярные выражения эквивалентны (для целей сопоставления):
-
/^(7|8|9)\d{9}$/
-
/^[789]\d{9}$/
-
/^[7-9]\d{9}$/
Объяснение:
-
(a|b|c)
является регулярным выражением "OR" и означает "a или b или c", хотя наличие скобок, необходимых для OR, также фиксирует цифру. Чтобы быть строго эквивалентным, вы бы закодировали (?:7|8|9)
, чтобы сделать его не захватывающей группой.
-
[abc]
- это "класс символов", который означает "любой символ из a, b или c" (класс символов может использовать диапазоны, например [a-d]
= [abcd]
)
Причина, по которой эти регулярные выражения аналогичны, заключается в том, что класс символов является сокращением для "или" (но только для одиночных символов). В чередовании вы также можете сделать что-то вроде (abc|def)
, которое не переводится в класс символов.
Ответ 2
Совет вашей команды почти прав, за исключением ошибки, которую он совершил. Как только вы узнаете, почему, вы никогда его не забудете. Взгляните на эту ошибку.
/^(7|8|9)\d{9}$/
Что это делает:
-
^
и $
обозначает привязанные соответствия, которые утверждают, что подшаблон между этими якорями является полным совпадением. Строка будет соответствовать только в том случае, если подшаблон совпадает со всем, а не только с разделом.
-
()
обозначает группу захвата.
-
7|8|9
обозначает соответствие либо 7
, 8
, либо 9
. Он делает это с чередованием, что и делает оператор трубы |
- чередуется между чередованиями. Это отступает между чередованием: если первое чередование не согласовано, движок должен вернуться до перемещения указателя во время совпадения чередования, чтобы продолжить соответствие следующему чередованию; В то время как класс символов может продвигаться последовательно. См. Это совпадение в движке регулярных выражений с отключенными оптимизациями:
Pattern: (r|f)at
Match string: carat
![matching with alternations between r and f alternations]()
Pattern: [rf]at
Match string: carat
![matching with character class instead class]()
-
\d{9}
соответствует девяти цифрам. \d
- сокращенный метасимвол, который соответствует любым цифрам.
/^[7|8|9][\d]{9}$/
Посмотрите, что он делает:
-
^
и $
обозначают также привязанные соответствия.
-
[7|8|9]
- класс символов . Любые символы из списка 7
, |
, 8
, |
или 9
могут быть сопоставлены, поэтому |
был добавлен неправильно. Это соответствует без возврата.
-
[\d]
- это класс символов, который обитает в метасимволе \d
. Комбинация использования символьного класса и одного метасимвола - плохая идея, между прочим, поскольку уровень абстракции может замедлить совпадение, но это только деталь реализации и применима только к некоторым реализациям регулярных выражений. JavaScript не один, но он делает подшаблон немного длиннее.
-
{9}
указывает, что предыдущая одиночная конструкция повторяется девять раз.
Оптимальное регулярное выражение /^[789]\d{9}$/
, потому что /^(7|8|9)\d{9}$/
захватывает ненужно, что накладывает снижение производительности на большинство реализаций регулярных выражений (javascript является одним из них, учитывая, что вопрос использует ключевое слово var
в коде, это, вероятно, JavaScript). Использование php, который работает на PCRE для preg matching оптимизирует отсутствие обратного отслеживания, однако мы тоже не в PHP, поэтому использование классов []
вместо чередования |
дает бонус производительности, так как совпадение не отступает, и поэтому оба совпадения и не работают быстрее, чем использование ваше предыдущее регулярное выражение.
Ответ 3
Первые 2 примера действуют по-разному, если вы ЗАМЕНЯете их чем-то. Если вы соответствуете этому:
str = str.replace(/^(7|8|9)/ig,'');
вы заменили бы 7 или 8 или 9 пустой строкой.
Если вы соответствуете этому
str = str.replace(/^[7|8|9]/ig,'');
вы замените 7
или 8
или 9
ИЛИ ВЕРТИКАЛЬНЫЙ БАР!!!! по пустой строке.
Я только что нашел это с трудом.