引用 - 捕获 - 问题
有人可以解释一下,为什么我可以使用 $1
两次并得到不同的结果?
perl -wle '"ok" =~ /(.*)/; sub { "huh?" =~ /(.*)/; print for @_ }->( "$1", $1 )'
(可在:如何在 Perl 中排除子匹配?)
Could someone explain, why I can use $1
two times and get different results?
perl -wle '"ok" =~ /(.*)/; sub { "huh?" =~ /(.*)/; print for @_ }->( "$1", $1 )'
(Found in: How to exclude submatches in Perl?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
@_
参数数组的行为与您想象的不同。子例程中@_
中的值实际上是真实参数的别名< /a>:当您这样说时:
s
的第一个参数中的$1
立即由字符串插值求值,但第二个参数不求值,只是注意到第二个值在子版本的@_
中是$1
(实际变量$1
,而不是它的值)。然后,在s
内,$1
的值会被正则表达式更改。现在,您的@_
有一个字符串"ok"
的别名,后跟$1
的别名,这些别名由 < code>print 在循环中。如果您将函数更改为这样:
甚至这样:
那么您将得到您期望的两行“ok”。有趣的是(有趣的奇特,不好笑哈哈)是这两个版本的
s
出于不同的原因产生了您预期的结果。my @a = @_;
版本在正则表达式获取$1
之前提取@_
中别名的当前值;local $1;
版本 本地化$1< /code> 变量给子进程,在
@_
中留下别名,从子进程外部引用$1
的版本:像这样的奇怪现象就是为什么你应该尽快将编号的正则表达式捕获变量的值复制到你的变量中,以及为什么你想在函数的开头解压
@_
(除非你知道为什么你不想这样做)。希望我没有过多地破坏术语,这是 Perl 中那些奇怪的角落之一,我一直远离它,因为我不喜欢玩弄剃须刀刀片。
The
@_
argument array doesn't behave the way you think it does. The values in@_
in a subroutine are actually aliases for the real arguments:When you say this:
The
$1
in the first argument tos
is immediately evaluated by the string interpolation but the second argument is not evaluated, it is just noted that the second value in the sub's version of@_
is$1
(the actual variable$1
, not its value). Then, insides
, the value of$1
is changed by your regular expression. And now, your@_
has an alias for the string"ok"
followed by an alias for$1
, these aliases are resolved by theprint
in your loop.If you change the function to this:
or even this:
Then you'll get the two lines of "ok" that you're expecting. The funny (funny peculiar, not funny ha-ha) is that those two versions of
s
produce your expected result for different reasons. Themy @a = @_;
version extracts the current values of the aliases in@_
before the regular expression gets its hands on$1
; thelocal $1;
version localizes the$1
variable to the sub leaving the alias in@_
referencing the version of$1
from outside the sub:Oddities like this are why you should always copy the values of the numbered regex capture variables to variables of your as soon as possible and why you want to unpack
@_
right at the beginning of your functions (unless you know why you don't want to do that).Hopefully I haven't butchered the terminology too much, this is one of those weird corners of Perl that I've always stayed away from because I don't like juggling razor blades.
示例代码利用了两个事实:
@_
数组的元素是实际标量参数的别名。特别是,如果元素$_[0]
被更新,相应的参数也会被更新(反之亦然)。$1
是一个全局变量(尽管动态作用域为当前 BLOCK),它自动包含来自上次成功模式匹配的()
的子模式。子例程的第一个参数是一个普通字符串 (
"ok"
)。第二个参数是全局变量$1
。但在打印参数之前,子例程内成功的模式匹配会改变它。The sample code makes use of two facts:
@_
array are aliases for the actual scalar parameters. In particular, if an element$_[0]
is updated, the corresponding argument is updated (and vice versa).$1
is a global variable (albeit dynamically scoped to the current BLOCK), which automatically contains the subpattern from()
from the last successful pattern match.The first argument to the subroutine is an ordinary string (
"ok"
). The second argument is the global variable$1
. But it is changed by the successful pattern match inside the subroutine, before the arguments are printed.发生这种情况是因为 perl 通过引用传递参数。
您所做的类似于:
当调用 sub foo 时, $_[1] 实际上是 $a 的别名,因此当修改 $a 时它的值也会被修改。
That happens because perl passes parameters by reference.
What you are doing is similar to:
When the sub foo is called, $_[1] is actually an alias for $a and so its value gets modified when $a is modified.