Шаблон тоже соответствует дефису - PullRequest
3 голосов
/ 19 августа 2010

У меня есть часть кода Perl (сопоставление с образцом), как это,

$var = "<AT>this is an at command</AT>";

if ($var =~ /<AT>([\s\w]*)<\/AT>/i)
{
    print "Matched in AT command\n";
    print "$var\n\n";
}

Работает нормально, если между тегами содержимого нет дефиса. Это не работает, если между строкой, присутствующей между тегами, вставлен дефис, как этот ... <AT>this is an at-command</AT>.

Может ли кто-нибудь исправить это регулярное выражение для соответствия, даже если дефис также вставлен ??

помогите мне, пожалуйста

Senthil

Ответы [ 5 ]

8 голосов
/ 19 августа 2010

В классе персонажей

Ваш шаблон содержит этот подшаблон:

[\s\w]*

[…] - это класс символов . Что-то вроде [aeiou] соответствует одному из строчных гласных. [^…] является отрицательным классом символов. [^aeiou] соответствует одному из всего, кроме строчных гласных.

\s - сокращение для класса символов пробела; \w для класса символов слова. Ни один из них не содержит дефис.

* - это ноль или более повторение спецификатор.

Теперь вы должны понять, почему этот шаблон не соответствует дефису: он соответствует нулю или более символов, которые являются пробелом или символом слова. Если вы хотите сопоставить дефис, вы можете включить его в класс символов.

[\s\w-]*

Если вы также хотите включить точку, вопросительный знак и восклицательный знак, например, то вы можете просто добавить их также:

[\s\w.!?-]*

Специальное примечание к дефису

Будьте осторожны при включении дефиса в класс персонажа. Он используется как метасимвол регулярного выражения в определении класса символов для определения диапазона символов. Например,

[a-z]

соответствует одному символу в диапазоне от 'a' до 'z' включительно. В отличие от

[az-]

соответствует одному из 3 символов: 'a', 'z' и '-'. Когда вы ставите - как последний элемент в классе символов, он становится буквальным дефисом вместо определения диапазона. Вы также можете указать его как элемент first или экранировать его (добавив обратную косую черту, как и другие метасимволы regex).

То есть следующие 3 класса символов идентичны:

[az-]         [-az]         [a\-z]

Похожие вопросы

4 голосов
/ 19 августа 2010

Вы можете просто добавить дефис в класс char как:

if ($var =~ /<AT>([\s\w-]*)<\/AT>/i)

Кроме того, поскольку в вашем регулярном выражении есть /, вы можете использовать другой разделитель, таким образом вы можете избежать экранирования /:

if ($var =~m{<AT>([\s\w-]*)</AT>}i)
2 голосов
/ 20 августа 2010

Используйте \ S вместо \ w.

if ($var =~ /<AT>([\s\S]*)<\/AT>/i) {
0 голосов
/ 19 августа 2010

Вам нужно добавить больше символов в ваш класс, например [\ s \ w -] * (как сказал вам codaddict).

Более того, возможно, вам следует использовать lookahead , чтобы соответствовать концу вашей команды («Я хочу соответствовать этому только в том случае, если за ним следует конечный оператор»), например:

if ($var =~ /<AT>([^<]*)(?=<\/AT>)/i)

[^ <] означает «любой символ (включая дефис), кроме« <». </p>

Вы можете даже добавить вид сзади:

if ($var =~ (?<=/<AT>)([^<]*)(?=<\/AT>)/i)

Для более сложных вещей (так как вам, кажется, нужен небольшой синтаксический анализатор), вы должны взглянуть на теорию грамматики и на lex / yacc.

0 голосов
/ 19 августа 2010

Если вы хотите иметь все между, и вы можете использовать

if ($var =~ /<AT>((?:(?!<AT>).)*)<\/AT>/i)

И это нечестно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...