Perl:s /// g的奇怪行为

时间:2018-05-15 10:30:32

标签: regex perl replace

我有一个正则表达式,它捕获字符串的某些部分。我想使用s /// g删除/替换其中一个捕获字符串的某些字符,但它有一个奇怪的行为。使用tr /// d,它可以得到所需的结果。

首先在这里输出我想要的代码使用tr:

use strict;
use warnings;

my $x = '01_02_john_jane_fred_2017.xml';

$x =~ /^(\d\d)_(\d\d)_((?:[a-z]+_?)+)_(\d{4})\.xml$/;

my $desc = $3;

$desc =~ tr/_//d;

print "---print \$1: $1\n";
print "---print \$2: $2\n";
print "---print \$3: $3\n";
print "---print \$desc: $desc\n";
print "---print \$4: $4\n";

这就是我得到的:

D:\>perl p0018.pl
---print $1: 01
---print $2: 02
---print $3: john_jane_fred
---print $desc: johnjanefred
---print $4: 2017

但如果我使用s /// g而不是tr /// d:

$desc =~ s/_//g;

我明白了:

D:\>perl p0018.pl
Use of uninitialized value $1 in concatenation (.) or string at p0018.pl line 14.
---print $1:
Use of uninitialized value $2 in concatenation (.) or string at p0018.pl line 15.
---print $2:
Use of uninitialized value $3 in concatenation (.) or string at p0018.pl line 16.
---print $3:
---print $desc: johnjanefred
Use of uninitialized value $4 in concatenation (.) or string at p0018.pl line 18.
---print $4:

这种行为有解释吗?我如何使用s而不是tr来获得所需的结果?

1 个答案:

答案 0 :(得分:10)

m//s///在成功匹配后设置匹配变量,而tr///则没有,因为它只是逐个字符的转换。在此使用s///只会放弃$1$2和& c的先前值。因为你正在做另一场比赛。在使用它们之前,只需将它们绑定到不同的变量即可。

my $x = '01_02_john_jane_fred_2017.xml';
$x =~ /^(\d\d)_(\d\d)_((?:[a-z]+_?)+)_(\d{4})\.xml$/;

my $first = $1;
my $second = $2;
my $desc = $3;
my $year = $4;
$desc =~ s/_//g;

print "---print \$first: $first\n";
print "---print \$second: $second\n";
# ...