【问题标题】:Perl: Strange behaviour of s///gPerl:s///g 的奇怪行为
【发布时间】:2018-05-16 06:33:26
【问题描述】:

我有一个正则表达式,它可以捕获字符串的某些部分。我想删除/替换使用 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 来获得所需的结果?

【问题讨论】:

  • 您使用的是 Windows,但您不知道如何从 cmd 复制输出。您需要右键单击,选择 Select(或 Mark 或其他东西),然后选择并按 Enter 键。或阅读howtogeek.com/howto/windows-vista/…
  • 我建议/^(\d+)_(\d+)_(\w+)_(\d+)\.xml$/ 除非您不能信任文件名的格式并且您需要验证它们以及解析信息。

标签: regex perl replace


【解决方案1】:

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";
# ...

【讨论】:

  • 请注意,只有 成功 正则表达式模式匹配会改变数字变量;一场失败的比赛会让他们不受影响。此外,tr/// 不会影响它们,因为它不使用正则表达式模式:它是一个简单的字符范围。
  • @Borodin 在我的真实案例中,我在捕获之前测试了匹配(如果...)。我在 SO 中省略了这个以简化问题。但是,谢谢你提供这些信息。我不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多