清除/重置所有正则表达式匹配变量的最佳方法是什么?
示例如何在正则表达式操作之间重置$1
并使用最近的匹配:
$_="this is the man that made the new year rumble";
/ (is) /;
/ (isnt) /;
say $1; # outputs "is"
示例在使用循环时这可能会出现问题:
foreach (...){
/($some_value)/;
&doSomething($1) if $1;
}
更新:我认为我不需要这样做,但是示例2只是一个例子。这个问题是关于重置匹配变量,而不是实现它们的最佳方式。
无论如何,最初我的编码风格更明确并且使用if-blocks。现在回到这个(例2)之后,阅读许多行代码会更加简洁,我会发现这种语法更快理解。
答案 0 :(得分:18)
您应该使用匹配的回报,而不是组变量的状态。
foreach (...) {
doSomething($1) if /($some_value)/;
}
如果匹配成功,$ 1等仅保证反映最近的匹配。除了比赛成功后,你不应该看着他们。
答案 1 :(得分:14)
正则表达式捕获*由成功匹配重置。要重置正则表达式捕获,可以使用保证匹配的普通匹配操作。
"a" =~ /a/; # Reset captures to undef.
是的,它看起来很奇怪,但你要求做一些奇怪的事情。
如果您修复您的代码,则不需要看起来很奇怪的解决方法。修复代码甚至会发现错误!
修正:
$_ = "this is the man that made the new year rumble";
if (/ (is) / || / (isnt) /) {
say $1;
} else{
... # You're currently printing something random.
}
和
for (...) {
if (/($some_pattern)/) {
do_something($1);
}
}
* - Backrefs是与之前捕获的文本匹配的正则表达式模式。例如\1
,\k<foo>
。你实际上是在谈论“正则表达式捕获缓冲区”。
答案 2 :(得分:5)
您应该测试匹配是否成功。例如:
foreach (...){
/($some_value)/ or next;
doSomething($1) if $1;
}
foreach (...){
doSomething($1) if /($some_value)/ and $1;
}
foreach (...){
if (/($some_value)/) {
doSomething($1) if $1;
}
}
根据$some_value
是什么,以及您希望如何处理匹配空字符串和/或0,您可能需要或可能不需要测试$1
。
答案 3 :(得分:1)
你应该这样做:
foreach (...) {
someFnc($1) if /.../;
}
但如果你想坚持自己的风格,那么请将其作为一个想法:
$_ = "this is the man that made the new year rumble";
$m = /(is)/ ? $1 : undef;
$m = /(isnt)/ ? $1 : undef;
print $m, "\n" if defined $m;
答案 4 :(得分:1)
补充现有的,有用的答案(以及通常在布尔上下文中测试匹配操作结果的明智建议,并且只有在测试成功的情况下才采取行动):
根据您的情况,您可以采用不同的方式解决问题:
免责声明:我不是一位经验丰富的Perl程序员;如果这种方法存在问题,请告诉我。
将匹配操作包含在do { ... }
块范围内,将所有与正则表达式相关的特殊变量($&
,$1
,...)纳入该块。
因此,你可以使用do { ... }
来防止这些特殊变量首先被设置(尽管来自块之外的先前正则表达式操作的那些显然仍然有效);例如:
$_="this is the man that made the new year rumble";
# Match in current scope; -> $&, $1, ... *are* set.
/ (is) /;
# Match inside a `do` block; the *new* $&, $1, ... values
# are set only *inside* the block;
# `&& $1` passes out the block's version of `$1`.
$do1 = do { / (made) / && $1 };
print "\$1 == '$1'; \$do1 == '$do1'\n"; # -> $1 == 'is'; $do1 == 'made'
$&
和$'
等变量。答案 5 :(得分:0)
将捕获物分配给列表的行为更接近您想要的声音。
for ("match", "fail") {
my ($fake_1) = /(m.+)/;
doSomething($fake_1) if $fake_1;
}