Perl:捕获变量不能设置为undef?

uz75evzq  于 2022-11-15  发布在  Perl
关注(0)|答案(3)|浏览(150)

我有几个带有捕获的正则表达式,很明显,捕获变量保留了上次有效捕获的值:

# Two scalars to use for regexp
$x = 'abc'; 
$y = 'def'; 

# first regexp
$x =~ /^(ab)/; 
$x = $1; 

# second regexp
$y =~ /^(de)/; 
$y = $1; 
print \"$x\n$y\";

输出为:

ab
de

下面是一行代码版本:

perl -e "$x='abc'; $y='def'; $x =~ /^(ab)/; $x=$1; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"

如果将$y='def'更改为$y='zdef'

perl -e "$x='abc'; $y='zdef'; $x =~ /^(ab)/; $x=$1; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"

输出为:

ab
ab

如果我想在$x=$1之后设置$1=undef以删除$1中的当前值

perl -e "$x='abc'; $y='zdef'; $x =~ /^(ab)/; $x=$1; $1=undef; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"

输出为:

Modification of a read-only value attempted at -e line 1.

显然,捕捉变量是不能改变的。
我想知道我该如何科普这个问题。我希望得到的结果是:

ab
..

其中..表示“空”。就像第一个正则表达式是undef($x='zabc)的情况:

perl -e "$x='zabc'; $y='def'; $x =~ /^(ab)/; $x=$1; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"

..
de
olqngx59

olqngx591#

您需要小心使用捕获变量$1(以及$2$3等)。它们在成功的模式匹配时被赋值(以及未赋值),因此您必须确保拥有正确的匹配。man perlvar声明(重点是successful):

$<digits> ($1, $2, ...)
               Contains the subpattern from the corresponding set of capturing
               parentheses from the last successful pattern match, ...

通常,您可以执行以下操作:

if ('abc' =~ /^(ab)/) {
    $x = $1;
}
if ('zdef' =~ /^(de)/) {
    $y = $1;
}

这样,您就永远不会得到指定的错误值。
然而,还有其他方法可以做到这一点。模式匹配本身给出一个返回值,这取决于上下文。

$n   = 'abc' =~ /^(ab)/;        # $n = 1 for "true". This is scalar context
($n) = 'abc' =~ /^(ab)/;        # $n = 'ab', the captured string. This is list context
$n = () = 'abc' =~ /(.)/g;      # $n = 3, for 3 matches. /g gives multiple matches
($f, $g) = 'abc' =~ /(.)/g;     # $f = 'a', $g = 'b'. List context
9lowa7mx

9lowa7mx2#

perl正则表达式通常使用全局变量。如果没有捕获,$1将是最后一个成功捕获的组。
正如我所说的,这是常见的,这是Perl的工作方式。
您可以做什么?首先,将所有捕获的组放入阵列,如下所示:

@captures = $y =~ /^(de)/;

然后用它工作。
二、使用ternar语句:

$y = $y =~ /(ho)/ ? $1 : undef;

或者你可以考虑这个包https://metacpan.org/pod/Regex::Object它对这类事情有帮助。但是你需要一些关于CPAN和对象的基本知识。

4ktjp1zp

4ktjp1zp3#

替换

$y =~ /^(de)/; 
$y = $1;

( $y ) = $y =~ /^(de)/;

$y = $y =~ /^(de)/ ? $1 : undef;

前者依赖于这样一个事实,即匹配运算符返回在列表上下文中调用时捕获的序列。
后者依赖于这样一个事实:在标量上下文中调用时,匹配运算符返回匹配是否成功。

相关问题