2009-08-03 97 views
6

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

我遇到的问题是我无法让替代部分工作。我正在查看手册页中的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 [email protected]; 
    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运行“/亚光/ “-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 

回答

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..."; 
} 
+0

啊,很好用`( ?选择采用:拍拍)`。我总是忘记你能做到这一点。 – chaos 2009-08-03 18:12:06

7

-r "matt",不-r "/matt/"运行它。您不需要并且实际上不能在您的选项字符串中提供模式分隔符。引号是qr中的分隔符。所以它实际上是在寻找matt的斜线,这是你运行它的方式,这不是你想要的。你试图用引号告诉Perl把你的模式字符串当作源代码来处理,但不幸的是你不能这么做。

所有这些模式附加你正在为其他选项做也不会工作。如果你想完成所有这些,你需要改变编译正则表达式的方式。像这样的东西可能会为/i/s做到这一点:

my $compd_pattern = qr/$pattern/ or die [email protected]; 
$compd_pattern = qr/$compd_pattern/i if $options{i}; 
$compd_pattern = qr/$compd_pattern/s if $options{s}; 

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