В чем разница между квадратными скобками и круглыми скобками в регулярном выражении?

Вот регулярное выражение, которое я создал для использования в JavaScript:

var reg_num = /^(7|8|9)\d{9}$/

Вот еще один, предложенный членом моей команды.

var reg_num = /^[7|8|9][\d]{9}$/

Правило должно подтверждать номер телефона:

  • Должно быть только десять цифр.
  • Первый номер должен быть любым из 7, 8 или 9.

3 ответа

Решение

Эти регулярные выражения эквивалентны (для сопоставления):

  • /^(7|8|9)\d{9}$/
  • /^[789]\d{9}$/
  • /^[7-9]\d{9}$/

Объяснение:

  • (a|b|c) является регулярным выражением "ИЛИ" и означает "a или b или c", хотя наличие скобок, необходимых для ИЛИ, также фиксирует цифру. Чтобы быть строго эквивалентным, вы должны написать (?:7|8|9) сделать его не захватывающей группой.

  • [abc] является "классом символов", что означает "любой символ из a, b или c" (класс символов может использовать диапазоны, например [a-d] знак равно [abcd])

Причина, по которой эти регулярные выражения похожи, состоит в том, что класс символов является сокращением для "или" (но только для одиночных символов). В чередовании вы также можете сделать что-то вроде (abc|def) который не переводится в класс персонажа.

Совет вашей команды почти верен, за исключением ошибки, которую он совершил. Как только вы узнаете почему, вы никогда не забудете это. Посмотрите на эту ошибку.

/^(7|8|9)\d{9}$/

Что это делает:

  • ^ а также $ обозначает привязанные соответствия, которые утверждают, что подшаблон между этими привязками является полным соответствием. Строка будет соответствовать только в том случае, если подшаблон соответствует всему, а не только разделу.
  • () обозначает группу захвата.
  • 7|8|9 обозначает совпадение любого из 7, 8, или же 9, Это делается с чередованием, что оператор труб | делает - чередуя чередования. Это возвращает назад между чередованиями: если первое чередование не сопоставлено, двигатель должен вернуться до того, как указатель переместился во время совпадения чередования, чтобы продолжить сопоставление следующего чередования; Принимая во внимание, что класс персонажа может продвигаться последовательно. Посмотрите это совпадение на движке регулярных выражений с отключенной оптимизацией:
Pattern: (r|f)at
Match string: carat

alternations

Pattern: [rf]at
Match string: carat

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, оптимизирует отсутствие обратного отслеживания, однако мы также не находимся в PHP, поэтому используем классы [] вместо чередований | дает выигрыш в производительности, так как совпадение не возвращается, и поэтому совпадает и терпит неудачу быстрее, чем при использовании вашего предыдущего регулярного выражения.

Первые 2 примера действуют совсем по-другому, если вы заменяете их чем-то. Если вы соответствуете по этому:

str = str.replace(/^(7|8|9)/ig,''); 

вы бы заменили 7, 8 или 9 пустой строкой.

Если вы соответствуете по этому

str = str.replace(/^[7|8|9]/ig,''); 

ты заменишь 7 или же 8 или же 9 ИЛИ ВЕРТИКАЛЬНЫЙ БАР!!!! по пустой строке.

Я только что выяснил это трудным путем.

Другие вопросы по тегам