Perl qr // 和替换

发布于 2024-07-30 05:06:04 字数 2321 浏览 8 评论 0原文

我正在编写一个小程序,它使用 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 运行它时,并输入替换文本 'matthew ',在文本“matt”上,它失败了。 为什么是这样?

编辑:

感谢大家的回答! 这确实非常有帮助。 我将您的建议合并为该问题的可行解决方案。 我必须以稍微不同的方式处理 /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

I'm writing a tiny program that takes user input using Getops, and based on it, the program will either try to match a pattern against some text, or substitute text for what matched.

The problem I'm having is that I can't get the substitution portion to work. I'm looking at the qr// entry in the man pages: http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators but I'm not having any luck with it. I tried to model my code exactly like the docs in this case. I compile a match pattern, and substitute that into a substitution.

Could someone point out where I'm going wrong? (Don't worry about security too much, this is only a little script for personal use)

Here's what I'm looking at:

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

When I run it with -r "/matt/" -i, and enter the replacement text 'matthew', on the text 'matt', it fails. Why is this?

EDIT:

Thanks for the answers guys ! That was really very helpful. I combined both of your suggestions into a working solution to the problem. I have to handle the /g flag a little differently. Here is the working sample:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

↙温凉少女 2024-08-06 05:06:04

正如 chaos 指出的,使用 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...";
}

As chaos points out, you will encounter some difficulties using qr//. Do you really need to precompile the pattern? If not, a strategy like this might work:

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/;

Update in response to your new code: you might consider using an approach like this:

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...";
}
帅气尐潴 2024-08-06 05:06:04

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

Run it with -r "matt", not -r "/matt/". You don't need to, and in fact can't, supply pattern delimiters in your option string. The quotes are the delimiters in your qr. So it's actually looking for matt with slashes around it, the way you're running it, which isn't what you want. You're trying to use the quotes to tell Perl to treat your pattern string like it were source code, but unfortunately you can't do that.

All those pattern appends you're doing for the other options also won't work. You'll need to change the way you compile the regex if you want to do all that. Something like this might do it for /i and /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};

For /g you'll need to support an alternate version of the search/replace. /g isn't a valid modifier to qr//.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文