引用 - 捕获 - 问题

sid*_*com 5 regex perl quote

有人可以解释一下,为什么我可以使用$1两次并得到不同的结果?

perl -wle '"ok" =~ /(.*)/; sub { "huh?" =~ /(.*)/; print for @_ }->( "$1", $1 )'
Run Code Online (Sandbox Code Playgroud)

(发现于:如何排除Perl中的子匹配?)

mu *_*ort 7

@_参数数组的行为不你认为它的方式.@_子例程中的值实际上是真实参数的别名:

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

当你这样说:

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

"ok" =~ /(.*)/;   
s("$1", $1);
Run Code Online (Sandbox Code Playgroud)

$1在第一个参数s立即被串插评价,但第二个参数不评估,它只是指出,在潜艇的版本的第二个值@_IS $1(实际变量$1,而不是它的价值).然后,在里面s,$1您的正则表达式会更改值.现在,你@_有一个字符串"ok"的别名后跟别名$1,这些别名由print你的循环解析.

如果您将功能更改为:

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

甚至这个:

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

然后你会得到你期待的两行"ok".有趣(有趣的奇怪,不好笑的哈哈)是这两个版本s产生你的预期结果出于不同的原因.该my @a = @_;版本@_在正则表达式获取之前提取别名的当前值$1; 该local $1;版本$1变量本地化为sub,使别名@_引用$1sub的外部版本:

本地修改列出的变量是封闭块,文件或eval的本地变量.

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

但愿我没有屠杀的术语太多,这是Perl中的那些奇怪的角落,我一直呆在距离,因为我不喜欢杂耍刀片掉之一.