Какие символы я должен экранировать в предварительно скомпилированном регулярном выражении Perl?

StackOverflow https://stackoverflow.com/questions/291163

Вопрос

Мне трудно определить, какие символы должен экранироваться при использовании конструкции Perl qr{}

Я пытаюсь создать многострочное предварительно скомпилированное регулярное выражение для текста, которое содержит множество обычно экранированных символов (#*.>:[]), а также содержит еще одно предварительно скомпилированное регулярное выражение.Кроме того, мне нужно максимально строго соответствовать в целях тестирования.

my $output = q{# using defaults found in .config
*
*
Options:
  1. opt1
> 2. opt2
choice[1-2?]: };

my $sc = qr{(>|\s)}smx;
my $re = qr{# using defaults found in .config
*
*
Options:
$sc 1. opt1
$sc 2. opt2
choice[1-2?]: }mx;

if ( $output =~ $re ) {
  print "OK!\n";
}
else {
  print "D'oh!\n";
}

Ошибка:

Quantifier follows nothing in regex; marked by <-- HERE in m/# using defaults found in .config
* <-- HERE 
*
Options:
(?msx-i:(>|\s)) 1. opt1
(?msx-i:(>|\s)) 2. opt2
choice[1-2?]: / at ./so.pl line 14.

Попытка избежать звездочек приводит к неудачному совпадению (выходные данные D'oh).Попытка избежать других надоедливых символов также приводит к неудачному совпадению.Я мог бы продолжать пробовать разные комбинации того, от чего следует убежать, но здесь много вариантов, и я надеюсь, что кто-нибудь сможет дать некоторое представление.

Это было полезно?

Решение

Вам необходимо экранировать разделитель для qr//, а также любые метасимволы регулярных выражений, которые вы хотите использовать в качестве литералов.Если вы хотите, чтобы это были буквальные *, вам нужно экранировать их, поскольку * является квантором регулярного выражения.

Ваша проблема заключается в различных добавленных вами флагах регулярных выражений./m ничего не делает, потому что вы не используете привязки начала или конца строки (^, $)./s ничего не делает, потому что вы не используете подстановочный знак.метасимвол.Параметр /x делает все пробелы в вашем регулярном выражении бессмысленными и превращает строку с # в комментарий к регулярному выражению.

Это то, что вы хотите, с удаленными флагами регулярных выражений и экранированием правильных элементов:

my $sc = qr{(>|\s)};

my $re = qr{# using defaults found in \.config
\*
\*
Options:
$sc 1\. opt1
$sc 2\. opt2
choice\[1-2\?]: };

Хотя Дэмиан Конвей рассказывает людям в Лучшие практики Perl всегда помещать эти параметры в свои регулярные выражения, теперь вы понимаете, почему он ошибается.Вам следует добавлять их только тогда, когда вы хотите того же, что они делают, и вам следует добавлять вещи только тогда, когда вы знаете, что они делают.:) Вот что вы можете сделать, если хотите использовать /x.Вам нужно экранировать любые буквальные пробелы, вам нужно как-то обозначить окончания строк и вам нужно экранировать буквальный символ #.То, что раньше было читаемо, теперь превратилось в беспорядок:

my $sc  = qr{(>|\s)};
my $eol = qr{[\r\n]+};

my $re  = qr{\# \s+ using \s+ defaults \s+ found \s+ in \s+ \.config $eol
\*                    $eol
\*                    $eol
Options:              $eol
$sc \s+ 1\. \s+ opt1   $eol
$sc \s+ 2\. \s+ opt2   $eol
choice\[1-2\?]: \s+
}x;

if ( $output =~ $re ) {
  print "OK!\n";
}
else {
  print "D'oh!\n";
}

Другие советы

Похоже, то, что ты действительно хочешь, это Ожидать, но больше всего вы ищете цитатамета оператор, который экранирует все символы, имеющие особое значение для регулярного выражения.

Чтобы ответить на ваш вопрос напрямую (однако), помимо символа отмены кавычек (в данном случае }) нужно как минимум убежать, .[$()|*+?{\

Как сказал Брайан, вы должны избегать метасимволов разделителя и регулярного выражения.Обратите внимание, что при использовании qr//x (которым вы являетесь), вы также должны экранировать пробелы и # (который является маркером комментария).Вероятно, вы на самом деле не хотите использовать /x здесь.Если вы хотите быть в безопасности, вы может экранируйте любой небуквенно-цифровой символ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top