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

Вот регулярное выражение, которое я создал для использования в 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

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}$/ захватывает ненужно, что накладывает снижение производительности на большинство реализаций регулярных выражений ( является одним из них, учитывая, что вопрос использует ключевое слово var в коде, это, вероятно, JavaScript). Использование , который работает на 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 ИЛИ ВЕРТИКАЛЬНЫЙ БАР!!!! по пустой строке.

Я только что нашел это с трудом.