引用 - 捕获 - 问题

发布于 2024-11-07 08:28:31 字数 285 浏览 0 评论 0原文

有人可以解释一下,为什么我可以使用 $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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浪漫之都 2024-11-14 08:28:31

@_ 参数数组的行为与您想象的不同。子例程中 @_ 中的值实际上是真实参数的别名< /a>:

数组@_是一个本地数组,但它的元素是实际标量参数的别名。

当您这样说时:

sub s {
    "huh?" =~ /(.*)/;
    print for @_;
}

"ok" =~ /(.*)/;   
s("$1", $1);

s 的第一个参数中的 $1 立即由字符串插值求值,但第二个参数不求值,只是注意到第二个值在子版本的 @_ 中是 $1 (实际变量 $1,而不是它的值)。然后,在 s 内,$1 的值会被正则表达式更改。现在,您的 @_ 有一个字符串 "ok" 的别名,后跟 $1 的别名,这些别名由 < code>print 在循环中。

如果您将函数更改为这样:

sub s {
    my @a = @_;
    "huh?" =~ /(.*)/;
    print for @a;
}

甚至这样:

sub s {
    local $1;
    "huh?" =~ /(.*)/;
    print for @_;
}

那么您将得到您期望的两行“ok”。有趣的是(有趣的奇特,不好笑哈哈)是这两个版本的 s 出于不同的原因产生了您预期的结果。 my @a = @_; 版本在正则表达式获取 $1 之前提取 @_ 中别名的当前值; local $1; 版本 本地化 $1< /code> 变量给子进程,在 @_ 中留下别名,从子进程外部引用 $1 的版本:

局部变量将列出的变量修改为封闭块、文件或 eval 的局部变量。

像这样的奇怪现象就是为什么你应该尽快将编号的正则表达式捕获变量的值复制到你的变量中,以及为什么你想在函数的开头解压 @_ (除非你知道为什么你不想这样做)。

希望我没有过多地破坏术语,这是 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:

The array @_ is a local array, but its elements are aliases for the actual scalar parameters.

When you say this:

sub s {
    "huh?" =~ /(.*)/;
    print for @_;
}

"ok" =~ /(.*)/;   
s("$1", $1);

The $1 in the first argument to s 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, inside s, 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 the print in your loop.

If you change the function to this:

sub s {
    my @a = @_;
    "huh?" =~ /(.*)/;
    print for @a;
}

or even this:

sub s {
    local $1;
    "huh?" =~ /(.*)/;
    print for @_;
}

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. The my @a = @_; version extracts the current values of the aliases in @_ before the regular expression gets its hands on $1; the local $1; version localizes the $1 variable to the sub leaving the alias in @_ referencing the version of $1 from outside the sub:

A local modifies the listed variables to be local to the enclosing block, file, or eval.

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.

童话 2024-11-14 08:28:31

示例代码利用了两个事实:

  • @_ 数组的元素是实际标量参数的别名。特别是,如果元素 $_[0] 被更新,相应的参数也会被更新(反之亦然)。
  • $1 是一个全局变量(尽管动态作用域为当前 BLOCK),它自动包含来自上次成功模式匹配的 () 的子模式。

子例程的第一个参数是一个普通字符串 ("ok")。第二个参数是全局变量$1。但在打印参数之前,子例程内成功的模式匹配会改变它。

The sample code makes use of two facts:

  • The elements of the @_ 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.

墨小沫ゞ 2024-11-14 08:28:31

发生这种情况是因为 perl 通过引用传递参数。

您所做的类似于:

my $a = 'ok';

sub foo {
  $a = 'huh?';
  print for @_;
}

my $b = $a;
foo($b, $a)

当调用 sub foo 时, $_[1] 实际上是 $a 的别名,因此当修改 $a 时它的值也会被修改。

That happens because perl passes parameters by reference.

What you are doing is similar to:

my $a = 'ok';

sub foo {
  $a = 'huh?';
  print for @_;
}

my $b = $a;
foo($b, $a)

When the sub foo is called, $_[1] is actually an alias for $a and so its value gets modified when $a is modified.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文