我有一个正则表达式,它捕获字符串的某些部分。我想使用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来获得所需的结果?
答案 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";
# ...