【问题标题】:Perl qr// and substitutionPerl qr// 和替换
【发布时间】:2010-11-16 10:58:50
【问题描述】:

我正在编写一个使用 Getops 接受用户输入的小程序,基于它,该程序将尝试将模式与某些文本进行匹配,或者用文本替换匹配的内容。

我遇到的问题是我无法让替换部分工作。我正在查看手册页中的 qr// 条目:http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators 但我没有任何运气。在这种情况下,我尝试像文档一样对我的代码进行建模。我编译了一个匹配模式,并将其替换为替换。

有人能指出我哪里出错了吗? (不要太担心安全问题,这只是个人使用的一个小脚本)

这是我正在查看的内容:

if($options{r}){

    my $pattern = $options{r};
    print "\nEnter Replacement text: ";
    my $rep_text = <STDIN>;

    #variable grab, add flags to pattern if they exist.
    $pattern .= 'g' if $options{g};
    $pattern .= 'i' if $options{i};
    $pattern .= 's' if $options{s};


    #compile that stuff
    my $compd_pattern = qr"$pattern" or die $@;
    print $compd_pattern; #debugging

    print "Please enter the text you wish to run the pattern on: ";
    my $text = <STDIN>;
    chomp $text;    

    #do work and display
    if($text =~ s/$compd_pattern/$rep_text/){ #if the text matched or whatever
        print $text;
    }
    else{
        print "$compd_pattern on \n\t{$text} Failed. ";
    }
} #end R FLAG

当我使用 -r "/matt/" -i 运行它并在文本 'matt' 上输入替换文本 'matthew' 时,它失败了。这是为什么呢?

编辑:

谢谢大家的回答!这真的很有帮助。我将您的两个建议都结合到了该问题的可行解决方案中。我必须稍微不同地处理 /g 标志。这是工作示例:

if($options{r}){

    my $pattern = $options{r};
    print "\nEnter Replacement text: ";
    my $rep_text = <STDIN>;
    chomp $rep_text;

    #variable grab, add flags to pattern if they exist.

    my $pattern_flags .= 'i' if $options{i};
    $pattern_flags .= 's' if $options{s};

    print "Please enter the text you wish to run the pattern on: ";
    my $text = <STDIN>;
    chomp $text;    

    #do work and display
    if($options{g}){
        if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/g){ #if the text matched or whatever (with the g flag)
            print $text;
        }
        else{
            print "$pattern on \n\t{$text} Failed. ";
        }
    }
    else{
        if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/){ #if the text matched or whatever
            print $text;
        }
        else{
            print "$pattern on \n\t{$text} Failed. ";
        }
    }
} #end R FLAG

【问题讨论】:

    标签: regex perl substitution qr-operator


    【解决方案1】:

    作为chaos points out,您在使用qr// 时会遇到一些困难。你真的需要预编译模式吗?如果没有,这样的策略可能会奏效:

    my $pattern      = 'matt';
    my $text         = 'Matt';
    my $rep_text     = 'Matthew';
    my $pattern_opts = 'i';
    
    print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/;
    

    更新以响应您的新代码:您可以考虑使用这样的方法:

    my ($orig, $patt, $rep, $flags) = qw(FooFooFoo foo bar ig);
    
    my $make_replacement = $flags =~ s/g//        ?
        sub { $_[0] =~ s/(?$flags:$patt)/$rep/g } :
        sub { $_[0] =~ s/(?$flags:$patt)/$rep/  }
    ;
    
    if ( $make_replacement->($orig) ){
        print $orig;
    }
    else {
        print "Failed...";
    }
    

    【讨论】:

    • 啊,(?opts:pat) 非常好。我总是忘记你能做到。
    【解决方案2】:

    使用-r "matt" 运行它,而不是-r "/matt/"。您不需要,事实上也不能,在您的选项字符串中提供模式分隔符。引号是qr 中的分隔符。所以它实际上是在寻找带有斜线的matt,这是你运行它的方式,这不是你想要的。您试图使用引号告诉 Perl 将您的模式字符串视为源代码,但不幸的是您不能这样做。

    您为其他选项所做的所有这些模式附加也将不起作用。如果你想做这一切,你需要改变编译正则表达式的方式。 /i/s 可能会这样做:

    my $compd_pattern = qr/$pattern/ or die $@;
    $compd_pattern = qr/$compd_pattern/i if $options{i};
    $compd_pattern = qr/$compd_pattern/s if $options{s};
    

    对于/g,您需要支持替代版本的搜索/替换。 /g 不是 qr// 的有效修饰符。

    【讨论】:

      猜你喜欢
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2011-02-15
      • 1970-01-01
      • 2018-08-21
      • 2021-01-31
      • 1970-01-01
      • 2017-11-11
      相关资源
      最近更新 更多