Perl:命名的捕获组默认为替换字符串

gk7wooem  于 2023-08-06  发布在  Perl
关注(0)|答案(2)|浏览(132)

下面的Perl代码在第二次尝试解引用捕获组“ext”时失败

use strict;
use warnings;

foreach(qw/2.1 2/){
#foreach(@ARGV){
    my $out= sprintf("%.2f", $_);
    $out =~ s/(?:(?<ext>\.[1-9]?)|\.0)0([^\w]|$)/$+{'ext'}/g;
    print ":".$out.":\n";
}

字符串
如何在替换字符串中设置捕获组的默认值,以防它没有被定义?
我相信还有其他几种方法可以解决这个问题,但是我相信不能为捕获组设置默认值肯定会再次出现-所以请帮助我解决这个问题。
随访:
..我在池上的建议下让它工作了,所以它读起来

$out =~ s{(?:(?<ext>\.[1-9]?)|\.0)0([^\w]|$)}{ $+{'ext'} // "" }eg;


只是没有别的办法了吗特别是因为这只适用于Perl的“e“valuate regex功能。这也必须以标准的正则表达式的方式出现,至少忽略捕获组的解引用,如果它没有被捕获在第一位,不是吗?

lpwwtiir

lpwwtiir1#

使用e修改器使替换零件成为表达式。

s{...}{ $+{ext} // "default" }eg

字符串
但是,您尝试实现的目标并不需要使用捕获,更不用说条件捕获和它们的默认值了。
看起来您正在尝试删除所有尾随的零,以及可能保留的尾随.。为此,您可以使用以下简单代码:

my $out = sprintf( "%.2f", $_ ) =~ s/0+\z//r =~ s/\.\z//r;


另一种看待它的方式是,只有两个子串可以被删除:.00,或者0。这给了我们以下解决方案:

my $out = sprintf( "%.2f", $_ ) =~ s/\.00\z|0\z//r;

cyvaqqii

cyvaqqii2#

如果您坚持使用命名组进行此操作...
不使用e修饰符,只需在交替上下文中定义一个空的 ext

use strict;
use warnings;

foreach(qw/2.1 2/){
    my $out= sprintf("%.2f", $_);
    $out =~ s/(?:(?<ext>\.[1-9]?)|(?<ext>)\.0)0([^\w]|$)/$+{'ext'}/g;
    print ":".$out.":\n";
}

字符串
产出

:2.1:
:2:


更简单的是,去掉命名捕获并使用 * 分支重置 *。
使用时保持便携。

use strict;
use warnings;

foreach(qw/2.1 2/){
#foreach(@ARGV){
    my $out= sprintf("%.2f", $_);
    $out =~ s/(?|(\.[1-9]?)|()\.0)0([^\w]|$)/$1/g;
    print ":".$out.":\n";
}


相同输出

:2.1:
:2:


有关详细信息,请参阅此处接受的答案:How to avoid warnings in Perl regex substitution with alternatives?

相关问题