Как использовать регулярные выражения в Perl, если и регулярное выражение, и строки являются переменными - PullRequest
2 голосов
/ 01 ноября 2019

У меня есть две переменные, поступающие из некоторых пользовательских данных. Одна - это строка, которую нужно проверить, а другая - регулярное выражение, как показано ниже.

Следующий код не работает.

my $pattern = "/^current.*$/";
my $name = "currentStateVector";

if($name =~ $pattern) {
    print "matches \n";
} else {
    print "doesn't match \n";
}

И следующий -.

if($name =~ /^current.*$/) {
    print "matches \n";
} else {
    print "doesn't match \n";
}

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

Ответы [ 2 ]

5 голосов
/ 01 ноября 2019

Используемые вами двойные кавычки интерполируют - они сначала оценивают, что внутри них (переменные, экранированные символы и т. Д.), И возвращают строку, построенную с результатами оценок и оставшимися литералами,См. Gory подробности синтаксического анализа конструкций цитирования для подробного обсуждения с большим количеством деталей.

И в вашем примере строки есть $/, которая является одной из глобальных переменных Perl (см. perlvar ), поэтому $pattern отличается от ожидаемого;распечатайте его, чтобы увидеть. (В этом случае / является ошибочным, как описано ниже, но точка стоит.)

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

my $pattern = q(^current.*$);

или, что лучше, использовать специфичный для регулярных выражений оператор qr

my $pattern = qr/^current.*$/;

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

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

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


Этоподнят в комментарии, что пользователи могут представить «шаблон» с дополнительными /. Это было бы неправильно, как упоминалось выше;должен быть задан только сам шаблон (окружен в командной строке ', чтобы оболочка не интерпретировала определенные символы в нем). Далее следует более подробная информация.

* * * / явно не предназначены для использования в качестве части шаблона, а скорее предназначены для использования с оператором сопоставления, чтобы разделить (заключить в кавычки) сам шаблон регулярного выражения (вбольшее выражение), чтобы можно было использовать строковые литералы в шаблоне. Или они используются для ясности и / или для возможности определения глобальных модификаторов (даже если они также могут быть указаны внутри шаблонов).

Но тогда, если пользователи вводят их вокруг шаблона, регулярное выражение будет использовать тесимволы как часть шаблона и будут пытаться соответствовать ведущему / и т.д .;это не удастся. Убедитесь, что пользователи знают, что им нужно задавать один шаблон без разделителей. Я бы проверил на наличие разделителей и, если найдется, напечатает сообщение (или продолжит с предупреждением) - им также может понадобиться фактические / в их шаблоне.

Обратите внимание, что с шаблоном, заданным в переменной, или с выражением, дающим шаблон во время выполнения, явный оператор сопоставления и разделители не нужны для сопоставления;переменная или возвращаемое выражение берется как шаблон поиска и используется для сопоставления. См. Основы (perlre) и Операторы связывания (perlop) .

Таким образом, вы можете просто сделать $name =~ $pattern или, конечно, $name =~ /$pattern/, где вы можете дать глобальные модификаторы после закрытия /

2 голосов
/ 01 ноября 2019

Косые черты являются частью оператора сопоставления m//, а не частью регулярного выражения.

Когда я заполняю регулярное выражение из пользовательского ввода

my $pattern = shift;

и запускаю скрипт как

58663971.pl '^current.*$'

соответствует.

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