Perl qr //和替换

时间:2009-08-03 17:49:34

标签: regex perl substitution qr-operator

我正在编写一个使用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

2 个答案:

答案 0 :(得分:11)

正如混乱所指出的那样,使用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...";
}

答案 1 :(得分:7)

使用-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//的有效修饰符。