Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Perl中用于替换的匹配数字_Regex_Perl_Substitution - Fatal编程技术网

Regex Perl中用于替换的匹配数字

Regex Perl中用于替换的匹配数字,regex,perl,substitution,Regex,Perl,Substitution,我有一个小剧本: my @list = ('R3_05_foo.txt','T3_12_foo_bar.txt','01.txt'); foreach (@list) { s/(\d{2}).*\.txt$/$1.txt/; s/^0+//; print $_ . "\n"; } 预期的产出将是 5.txt 12.txt 1.txt 但是相反,我得到了 R3_05.txt T3_12.txt 1.txt 最后一个很好,但我无法理解为什么正则表达式在这种情况下为我提

我有一个小剧本:

my @list = ('R3_05_foo.txt','T3_12_foo_bar.txt','01.txt');

foreach (@list) {
    s/(\d{2}).*\.txt$/$1.txt/;
    s/^0+//;
    print $_ . "\n";
}
预期的产出将是

5.txt
12.txt
1.txt
但是相反,我得到了

R3_05.txt
T3_12.txt
1.txt
最后一个很好,但我无法理解为什么正则表达式在这种情况下为我提供了
$1
的字符串开头。

试试这种模式

foreach (@list) {
    s/^.*?_?(?|0(\d)|(\d{2})).*\.txt$/$1.txt/;
    print $_ . "\n";
}

说明:

我在这里使用分支重置功能(即,
(?|…()…|…())
),它允许在一个引用中放置多个捕获组(
$1
)。因此,您可以避免使用第二个替换来修剪捕获左侧的零

要删除数字前开头的所有内容,我使用:

.*?     # all characters zero or more times 
        # ( ? -> make the * quantifier lazy to match as less as possible)
_?      # an optional underscore


请注意,您可以确保只有2个数字添加一个前瞻,以检查是否有以下数字:

s/^.*?_?(?|0(\d)|(\d{2}))(?!\d).*\.txt$/$1.txt/;

(?!\d)
表示后面没有数字。

我将修改您的正则表达式。尝试使用以下代码:

my @list = ('R3_05_foo.txt','T3_12_foo_bar.txt','01.txt');

foreach (@list) {
    s/.*(\d{2}).*\.txt$/$1.txt/;
    s/^0+//;
    print $_ . "\n";
}

问题是,
s//
中的第一部分与您认为它的功能相匹配,但第二部分并没有取代您认为它应该取代的功能<代码>s//将仅替换先前匹配的内容。因此,要替换类似于
T3\uu
的内容,您也必须匹配它

s/.*(\d{2}).*\.txt$/$1.txt/;

这里的问题是替换正则表达式不覆盖整个字符串,因此只替换部分字符串。但是,对于一个简单的问题,您使用的是一个相当复杂的解决方案

似乎您想要的是从字符串中读取两位数字,然后在其末尾添加
.txt
。那么,为什么不这样做呢

my @list = ('R3_05_foo.txt','T3_12_foo_bar.txt','01.txt');

for (@list) {
    if (/(\d{2})/) {
        $_ = "$1.txt";
    }
}
要克服前导零效应,可以通过向数字加零来强制转换为数字:

$_ = 0+$1 . ".txt";

我以前有过,但我的输出只有一位数。确定吗?我的输出:perl test.pl 5.txt 12.txt 1.txt