括号如何改变正则表达式匹配的结果?

4

有人能解释一下以下两个语法之间的区别吗:

($x) = $a =~ /(\d+)/;

$y = $a =~ /(\d+)/;

在这个例子中,如果 $a=100lkj,那么$x = 100但是$y = 1
通过这段代码,我试图从$a字符串中提取数值。
我不太清楚为什么要这样做?
3个回答

6
当您在括号内写入变量时,它会强制使用列表上下文。这意味着您想要分配给该变量的内容也将被解释为列表。
在您的情况下,您有一个普通匹配。匹配的返回值是一个包含所有匹配项的列表。如果您将列表强制应用于标量上下文,则返回此列表中条目的数量。因此,您有1个匹配项,这意味着该列表包含1个匹配项。
不建议使用正则表达式的返回值。
您可以使用匹配项(从括号中)的变量 $1,$2,$3,...
在您的情况下:
$a =~ /(\d+)/;
$x = $1;

顺便提一下:$a$b是用于sort的特殊变量,请不要使用它们 :)。
($x) = $a =~ /(\d+)/;
# $x is the first element of the RegEx return value
# ($x, $y, $z) = $a =~ /(\d)(\d)(\d)/;
# $x = first match, $y = second and so on.

为什么不建议使用正则表达式的返回值? - Nathan Fellman
没有数组上下文。请参见http://friedo.com/blog/2013/07/arrays-vs-lists-in-perl - simbabque
是的,你说得对。我刚刚意识到了这一点:这里 - user1558455
Searches a string for a pattern match, and in scalar context returns true if it succeeds, false if it fails. - user1558455
“使用正则表达式的返回值并不是很推荐”?????恰恰相反,我不喜欢使用全局变量,所以我强烈推荐使用它。此外,您的代码在使用$1之前没有检查匹配是否成功,因此它可能包含垃圾数据。如果您想避免使用返回值,您必须使用my $x = $a =~ /(\d+)/ ? $1 : undef;而不是my ($x) = $a =~ /(\d+)/;。但那太傻了。 - ikegami

4
因为正则表达式测试通常在布尔上下文中使用,标量上下文返回的始终是成功或失败,而不是捕获值,只有列表上下文才会给你捕获到的值。如果它总是返回一个捕获的值,那么捕获的 '0' 在布尔测试中看起来会像失败。
就我而言,我强烈建议在可能的情况下使用返回值; 但要这样做,您必须使用列表上下文,例如列表分配。

1
在列表模式下,=~ 返回匹配项的列表。如果您的 $aabc123def456ghi,第一个表达式将返回 (123, 456)。您将第一个匹配项分配给 $x
在标量模式下,=~ 运算符返回找到的匹配数,在您的情况下为 1。
要提取值,请不要使用正则运算符的返回值,而是使用 $&$1 .. $9 变量。

2
没有/g标志,因此它不会尝试匹配多次。 - ysth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接