代码之家  ›  专栏  ›  技术社区  ›  Shubham

如何在Perl中使用regex变量

  •  3
  • Shubham  · 技术社区  · 15 年前

    我想这个问题是重复的,但是搜索对我没有帮助。

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

    我想要一个外置的 $pattern 在正则表达式中。我该怎么做?当前返回:

    在main.pm第20行打印时使用未初始化的值$1。

    5 回复  |  直到 8 年前
        1
  •  3
  •   daxim Fayland Lam    15 年前

    $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
  •  2
  •   Axeman maxelost    15 年前

    当我把这个字符串编译成regex时,就像这样:

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

    我得到了我认为我应该得到的,以下regex:

    (?-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 把比赛放到 "list context" 并返回列表中的捕获。在这里,我只期望一个值,所以这就是我所提供的。

    最后,问题的一个根本原因是,您不需要在字符串中指定表达式,以便您的regex“可移植”。您可以让Perl预编译表达式。这样,您只关心字符对regex的指令是什么,而不关心是否 节约 直到它编译成表达式为止。

    已编译的regex会正确地将自己插入到其他regex中。因此,您可以得到一个可移植的表达式,它既可以插入字符串,也可以正确地处理字符串中可能丢失的指令。

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

    是你所需要的。然后你可以使用它,就像你那样。尽管,将parens放在整个事物周围,会返回整个匹配的表达式(而不仅仅是引号之间的表达式)。

        3
  •  1
  •   daxim Fayland Lam    15 年前

    匹配模式中不需要括号。它将匹配整个模式并返回 $1 我猜这是不匹配的,但我只是猜测。

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

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

    这些是 clustering, non-capturing parentheses .

    你的做法是正确的。

        4
  •  1
  •   daxim Fayland Lam    15 年前

    已经给出了解决方案,我想指出 window.open 呼叫可能有 多个参数 包括在 "" 按逗号分组,如:

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

    函数名和圆括号之间可能有空格,因此我将使用稍微不同的regex:

    my $pattern = qr{
        javascript:window.open\s*
        \(
        ([^)]+)
        \)
    }x;
    
    print $1 if $text =~ /$pattern/;
    

    现在所有参数都在 $1 然后可以用 split /,/, $stuff 等等。

        5
  •  0
  •   Tore A.    15 年前

    它报告一个未初始化的值,因为$1未定义。$1是未定义的,因为您已经通过在模式周围包装第二组括号创建了嵌套的匹配组。如果没有与您的模式匹配的内容,那么它也将是未定义的。