Как иметь переменную в качестве регулярного выражения в Perl - PullRequest
3 голосов
/ 17 августа 2010

Я думаю, что этот вопрос повторяется, но поиск мне не помог.

my $pattern = "javascript:window.open\('([^']+)'\);";
$mech->content =~ m/($pattern)/;
print $1;

Я хочу иметь внешний $pattern в регулярном выражении.Как я могу это сделать?Текущее значение возвращает:

Использование неинициализированного значения $ 1 в печати в строке main.pm 20.

Ответы [ 5 ]

3 голосов
/ 17 августа 2010

$1 был пуст, поэтому матч не удался. В моем примере я создам постоянную строку, и я знаю, что она будет соответствовать шаблону.

Объявите ваше регулярное выражение с qr , а не как простую строку. Кроме того, вы захватываете дважды, один раз в $pattern для скобок вызова open, один раз в операторе m для всего этого, поэтому вы получите два результата. Вместо $1, $2 и т. Д. Я предпочитаю присваивать результаты массиву.

my $pattern = qr"javascript:window.open\('([^']+)'\);";
my $content = "javascript:window.open('something');";
my @results = $content =~ m/($pattern)/;
# expression return array
# (
#     q{javascript:window.open('something');'},
#     'something'
# )
2 голосов
/ 17 августа 2010

Когда я скомпилирую эту строку в регулярное выражение, вот так:

my $pattern = "javascript:window.open\('([^']+)'\);";
my $regex   = qr/$pattern/;

Я получаю именно то, что, как я думаю, должен получить, следующее регулярное выражение:

(?-xism:javascript:window.open('([^']+)');)/

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

javascript:window.open'fum';

, но не

javascript:window.open('fum');

Одна вещь, которую вы должны изучить, это то, что в Perl, "\(" - это то же самое, что и "(" выпросто говорю Perl, что вы хотите литерал '(' в строке.Чтобы получить длительные побеги, вам нужно удвоить их.

my $pattern = "javascript:window.open\\('([^']+)'\\);";
my $regex   = qr/$pattern/;

Фактически сохраняет литерал ( и дает:

(?-xism:javascript:window.open\('([^']+)'\);)

Что я и хочу, что вы хотите.

Что касается вашего вопроса, вы должны всегда проверять результаты матча, прежде чем использовать его.

if ( $mech->content =~ m/($pattern)/ ) { 
     print $1;
}

имеет гораздо больше смысла.И если вы хотите увидеть это независимо, то это уже подразумевает, что это может не иметь значения.то есть вы, возможно, ничего не соответствовали.В этом случае лучше поставить альтернативы

$mech->content =~ m/($pattern)/;
print $1 || 'UNDEF!';

Однако я предпочитаю захватывать мои захваты в одном и том же утверждении, например так:

my ( $open_arg ) = $mech->content =~ m/($pattern)/;
print $open_arg || 'UNDEF!';

Парень вокруг $open_arg ставитсопоставить с "списком контекста" и вернуть записи в списке.Здесь я ожидаю только одного значения, так что это все, что я предусматриваю.

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

Скомпилированное регулярное выражение будет правильно интерполироваться в другие регулярные выражения.Таким образом, вы получаете переносимое выражение, которое интерполирует так же хорошо, как и строку - и, в частности, правильно обрабатывает инструкции, которые могут быть потеряны в строке.

my $pattern = qr/javascript:window.open\('([^']+)'\);/;

Это все, что вам нужно.Тогда вы можете использовать его, как и вы.Хотя, помещая в скобки все это, можно было бы вернуть все совпадающее выражение (а не только то, что находится в кавычках).

1 голос
/ 17 августа 2010

Решения уже даны, я хотел бы отметить, что вызов window.open может иметь несколько параметров , включенных в "" и сгруппированных по запятой, как:

javascript:window.open("http://www.javascript-coder.com","mywindow","status=1,toolbar=1");

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

my $pattern = qr{
    javascript:window.open\s*
    \(
    ([^)]+)
    \)
}x;

print $1 if $text =~ /$pattern/;

Теперь у вас есть все параметры в $1 и вы можете обработать их потомsplit /,/, $stuff и т. Д.

1 голос
/ 17 августа 2010

Вам не нужны скобки в шаблоне совпадения.Он будет соответствовать целому шаблону и вернет его как $1, что, я думаю, не соответствует, но я только предполагаю.

$mech->content =~ m/$pattern/;

или

$mech->content =~ m/(?:$pattern)/;

Это кластеризация, не захватывая скобки .

То, как вы это делаете, правильно.

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

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

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