В чем разница между () и [] в регулярном выражении? - PullRequest
8 голосов
/ 28 октября 2009

Допустим,

/(a|b)/ против /[ab]/

Ответы [ 3 ]

19 голосов
/ 28 октября 2009

В приведенном выше примере нет большой разницы (на большинстве языков). Основное различие заключается в том, что версия () создает группу, на которую может ссылаться \1 в матче (или иногда $1). Версия [] этого не делает.

Кроме того,

/(ab|cd)/  # matches 'ab' or 'cd'
/[abcd]/   # matches 'a', 'b', 'c' or 'd'
7 голосов
/ 28 октября 2009

() в регулярном выражении используется для группировки регулярных выражений, что позволяет применять операторы ко всему выражению, а не к одному символу. Например, если у меня есть регулярное выражение ab, то ab* относится к a, за которым следует любое число b с (например, a, ab, abb и т. Д.) в то время как (ab)* относится к любому числу повторений последовательности ab (например, пустая строка, ab, abab и т. д.). Во многих механизмах регулярных выражений () также используется для создания ссылок, на которые можно ссылаться после сопоставления. Например, в Ruby после выполнения "foo" =~ /f(o*)/, $1 будет содержать oo.

| в регулярном выражении указывает на чередование; это означает выражение до бара или выражение после него. Вы можете сопоставить любую цифру с выражением 0|1|2|3|4|5|6|7|8|9. Вы часто будете видеть чередование, заключенное в набор скобок, для группировки или захвата подвыражения, но это не обязательно. Вы также можете использовать чередование в более длинных выражениях, таких как foo|bar, чтобы указать либо foo, либо bar.

Вы можете выразить каждое регулярное выражение (в формальном, теоретическом смысле, а не в расширенном смысле, который используют многие языки), просто чередованием |, закрытием клини *, конкатенацией (просто написанием двух выражений рядом друг с другом без ничего между) и скобки для группировки. Но это было бы довольно неудобно для сложных выражений, поэтому обычно доступны несколько сокращений. Например, x? - это просто сокращение для |x (то есть пустой строки или x), а y+ - сокращение для yy*.

.

[] - это, по сути, сокращение для чередования | всех символов или диапазонов символов в нем. Как я уже сказал, я мог бы написать 0|1|3|4|5|6|7|8|9, но гораздо удобнее написать [0-9]. Я также могу написать [a-zA-Z] для обозначения любого письма. Обратите внимание, что хотя [] обеспечивает группировку, они обычно не вводят новую ссылку, на которую можно ссылаться позже; для этого вам нужно заключить их в скобки, например ([a-zA-Z])

Итак, ваши два примера регулярных выражений эквивалентны в том, что они совпадают, но (a|b) установит первое совпадение на соответствующий символ, в то время как [ab] не создаст никаких ссылок на совпадения.

6 голосов
/ 28 октября 2009

Во-первых, говоря о регулярных выражениях, часто важно указать, о каких регулярных выражениях вы говорите. Существует несколько вариантов (например, традиционные регулярные выражения POSIX, Perl и Perl-совместимые регулярные выражения (PCRE) и т. Д.).

Предполагая, что PCRE или что-то очень похожее, что часто является наиболее распространенным в наши дни, есть три ключевых различия:

  1. Используя группы в скобках, вы можете проверить параметры, состоящие из более чем одного символа. Так что / (a ​​| b) / может быть вместо /(abc|defg)/.
  2. Группы в скобках выполняют операцию захвата, чтобы вы могли извлечь результат (чтобы он совпадал с «b», вы могли вернуть «b» и увидеть это). / [ab] / нет. Операция захвата может быть переопределена добавлением?: Вроде так: / (?: a | b) /
  3. Даже если вы переопределите поведение захвата в круглых скобках, базовая реализация все равно может быть быстрее для [], когда вы проверяете отдельные символы (хотя ничто не говорит, что не захват (?: A | b) не может быть оптимизирован как особый случай в [ab], но компиляция регулярных выражений может занять немного больше времени.)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...