2012-05-21 9 views
2

Что касается регулярных выражений PCRE, в чем разница между [abc] и (a | b | c)?Разница между [abc] и (a | b | c)

+3

[Использование альтернативного или символьного класса для односимвольного совпадения?] (Http://stackoverflow.com/questions/4724588/using-alternation-or-character-class-for-single-character-matching) имеет несколько интересных ответы. – stema

+0

Это другое сообщение было полезно. Thanks – user1032531

ответ

8

Узоры в вашем вопросе совпадают с тем же текстом. С точки зрения реализации они соответствуют различным автоматам и побочным эффектам (, т. Е., независимо от того, захватывают ли они подстроки).

В комментарии ниже, Garrett Albright указывает на тонкое различие. В то время как (.|\n) соответствует любому персонажу, [.\n] соответствует литеральной точке или символу новой строки. Хотя точка больше не является специальной внутри класса символов, другие символы, такие как -, ^ и ], а также такие последовательности, как [:lower:], принимают специальные значения внутри класса символов. Уход необходим для сохранения специальной семантики из одного контекста в другой, но иногда это возможно, например, в случае \1 как архаичный способ написания $1 вне класса персонажа. Внутри класса символов \1 всегда соответствует символу SOH.

Классы символов ([...]) оптимизированы для соответствия одному из некоторого набора символов, а альтернативы (x|y) позволяют использовать более общий выбор различной длины. Вы будете видеть лучшую производительность, если будете придерживаться этих принципов дизайна. Реализационные преобразования преобразуют исходный код, например /[abc]/, в автоматы с конечным состоянием, обычно NFAs. То, что мы считаем двигателями регулярных выражений, - это более или менее бухгалтеры, которые помогают выполнять эти целевые государственные машины. Достаточно умный компилятор регулярных выражений будет генерировать одинаковый машинный код для эквивалентных регулярных выражений, но это сложно и дорого в общем случае из-за lurking exponential complexity.

Для ознакомления с теорией за регулярными выражениями читайте “How Regexes Work” от Марка Домина. Для более глубокого изучения рассмотрим An Introduction to Formal Languages and Automata от Peter Linz.

+0

Когда вы будете использовать один над другим? Что вы подразумеваете под «они соответствуют различным автоматам и захвату подстроки»? Спасибо – user1032531

+0

Если a, b и c - это просто буквы, конечно (как я думаю, это подразумевается). Очевидно, что если они могут стоять за слова, это совершенно другая семантика. – kratenko

+0

Я обнаружил, что иногда вариант квадратной скобки не работает должным образом для забавных символов, таких как '\ n' или' \ r'. Например, чтобы уловить весь текст между FOO и BAR, включая символы новой строки, '/ FOO ((. | \ N) +) BAR /' работает, тогда как '/ FOO ([. \ N] +) BAR /' не делает. Однако это может быть специфично для реализации. Я нашел другие отличия, которые я не могу вспомнить с головы.Во всяком случае, как правило, я попытаюсь использовать '[ab]' first, так как это более читаемо, а затем дайте '(a | b)' попытку, если что-то не работает. –

1

(после прочтения ответа Грега): Если они оцениваются по-разному, они должны зависеть от любой программы, к которой вы их кормите. Выберите, что вы пытаетесь проверить. Вы хотите проверить пул допустимых символов или хотите проверить значения. - Иногда это может показаться одним и тем же, но за этим может быть другое намерение. Затем выберите то, что отражает ваши намерения.

0

Форма, использующая квадратные скобки, намного быстрее с помощью PCRE, особенно если включена компиляция JIT. Он просто проверяет бит в битете, а другой перечитывает символ для каждой альтернативы. Я думал об оптимизации, которая бы обнаруживала такие случаи, поскольку многие не знают, что классы символов могут использоваться внутри квадратных скобок, и они используют ([a-z] | \ s) + вместо [a-z \ s] +.

Смежные вопросы