Какие буквальные символы следует избегать в регулярном выражении?
Я просто написал регулярное выражение для использования с php-функцией preg_match
, которая содержит следующую часть:
[\w-.]
Чтобы соответствовать любому символу слова, а также знаку минуса и точке. Хотя он работает в preg_match, я попытался поместить его в утилиту под названием Reggy, и он жалуется на "Пустой диапазон в char класс". Судебное разбирательство и ошибка научили меня, что эта проблема была решена путем выхода из знака минус, превращая регулярное выражение в
[\w\-.]
Так как оригинал, похоже, работает в PHP, мне интересно, почему я должен или не должен избегать знака минус, и - поскольку точка также является символом со значением в PHP - почему мне не нужно было бы избегать точка. Является ли утилита, которую я использую, просто глупо, работает ли она с другим диалектом regex или действительно ли мое регулярное выражение неверно, и мне просто повезло, что preg_match позволяет мне с ним справиться?
Ответы
Ответ 1
Во многих реализациях регулярных выражений применяются следующие правила:
Метасимволы внутри класса символов:
-
^
(отрицание)
-
-
(диапазон)
-
]
(конец класса)
-
\
(escape char)
Таким образом, все это должно быть экранировано. Есть некоторые угловые случаи:
-
-
не требуется экранирование, если оно помещено в самом начале или в конце класса ([abc-]
или [-abc]
). В довольно многих реализациях регулярных выражений также не требуется экранирование при размещении непосредственно после диапазона ([a-c-abc]
) или короткого символьного класса ([\w-abc]
). Это то, что вы наблюдали.
-
^
не требуется экранирование, если оно не находится в начале класса: [^a]
означает любой char кроме a
, а [a^]
соответствует либо a
, либо ^
, что равно: [\^a]
-
]
не требует экранирования, если это единственный символ в классе: []]
соответствует char ]
Ответ 2
[\w.-]
-
.
обычно означает любой символ, но между []
не имеет особого значения
-
-
между []
указывает диапазон, если только он не экранировался или не был первым или последним символом между []
Ответ 3
Пока действительно некоторые символы должны быть экранированы в регулярном выражении, вы спрашиваете не о regex, а о классе символов. Там, где символ штриха является особым.
вместо того, чтобы ускользнуть от него, вы можете поместить его в конец класса, [\w.-]
Ответ 4
Полная остановка теряет свой мета-смысл в классе символов.
-
имеет особое значение в классе символов. Если он не помещен в начале или в конце квадратных скобок, он должен быть экранирован. В противном случае он обозначает диапазон символов (A-Z
).
Вы активировали другой специальный случай. [\w-.]
работает, потому что \w
не обозначает один символ. Таким образом, PCRE не может создать диапазон символов. \w
- возможно некогерентный класс символов, поэтому не существует конечного символа, который можно было бы использовать для создания диапазона Z till .
. Также полная остановка .
должна предшествовать первому символу ascii a
, который мог бы соответствовать \w
. Конструкция не существует. Следовательно, -
работал без побега для вас.
Ответ 5
Если вы используете php и вам нужно избегать специальных символов регулярных выражений, просто используйте preg_quote
:
Пример из php.net:
<?php
// In this example, preg_quote($word) is used to keep the
// asterisks from having special meaning to the regular
// expression.
$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/" . preg_quote($word, '/') . "/",
"<i>" . $word . "</i>",
$textbody);
?>