正则匹配返回值和正则相关变量

Perl正则匹配返回值

正则匹配的返回值情况比较复杂,具体可参考perldoc perlop。大致可总结为:

  • 在标量上下文中,正则匹配总是在匹配成功时返回1表示布尔真,匹配失败时返回undef
  • 在列表上下文中:
    • 匹配失败时,总是返回空列表,表示布尔假
    • 匹配成功时,如果使用了小括号分组捕获,则返回本次匹配各分组捕获的内容列表
    • 匹配成功时,如果未使用小括号分组捕获,则在未使用g修饰符时返回列表(1),在使用了g修饰符时返回全局匹配成功的内容列表

例如:

# 在标量上下文,正则匹配可直接作为判断条件
my $str = "abAB12cdCD34";
say "matched" if($str =~ /\d+/);
say "not matched" if($str =~ /xy/);

# 在列表上下文,匹配失败时,返回空列表
my @arr = $str =~ /xy/;
say ~~@arr;    # 0

# 在列表上下文,匹配成功,且使用小括号分组捕获时,返回各分组内容
my @arr = $str=~/(\d+)/;
say "@arr";   # 12
@arr = $str=~/(\d+)[^0-9]+(\d+)/;
say "@arr";   # 12 34

# 在列表上下文,匹配成功,且未使用小括号分组捕获时,
# 如果未使用g修饰符全局匹配,则返回列表`(1)`
# 如果使用g修饰符全局匹配,则返回全局匹配成功的内容列表
my @arr1 = $str=~/\d+/;
say "@arr1";   # 1
my @arr2 = $str=~/\d+/g;
say "@arr2";   # 12 34

Perl正则匹配相关变量

Perl提供了一些和正则表达式相关的内置特殊变量,通过这些变量,可以访问某次正则匹配完成之后的一些数据。

例如,Perl正则匹配在标量上下文不会返回匹配成功的内容,但可以通过特殊变量$&来获取匹配到的内容:

my $str = "abAB12cdCD34";
say "matched: $&" if($str =~ /\d+/);

下面是正则表达式相关的特殊变量总结,其中一部分在后面内容涉及到的时候还会解释。

$1 $2 $3...
保存了各个分组捕获的内容

$&
$MATCH
保存了本次匹配到的内容

$`
$PREMATCH
保存了本次匹配起始位置之前的内容

$'
$POSTMATCH
保存了本次匹配结束位置之后的内容

对于$` $& $',它们保存的分别是本次匹配时,匹配内容前的内容、匹配到的内容和匹配内容后的内容。例如,对于正则匹配"aAbBcC"=~/bB/来说,匹配后它们的内容如下所示:

 (aA)(bB)(cC)
 |    |   |
 $`   $&  $'

在以前的Perl版本中,使用$` $& $'会有性能问题,每次匹配成功后都会拷贝对应的字符串到这三个变量中,但是从Perl v5.20开始,Perl采用了写时复制(copy-on-write)技术,只有确实使用了这些变量时,才会拷贝对应的字符串保存到这三个变量中,因此不用再担心使用这三个变量时的性能问题。

这些特殊变量是只读的,每次正则匹配时Perl会自动重置这些变量。这些变量只在当前作用域内有效,并且只在本次正则匹配后、下次正则匹配前有效。

$str = "abbc123";
$str=~/a(.*)c/;
say $1;
$str=~/a.*c/;
say $1;   # undef

还有几个比较常用的特殊变量是:

$+
$LAST_PAREN_MATCH
最后一个匹配成功的分组括号所匹配的内容(PAREN是括号parentheses的缩写)

%+
%LAST_PAREN_MATCH
保存本次匹配过程中所有命名分组捕获的内容,hash的key是分组名称,value是分组捕获的内容

@-
@LAST_MATCH_START
@+
@LAST_MATCH_END
前两个数组变量保存了各个分组匹配的起始位置。后两个数组变量保存了各个分组匹配的结束位置。

@- @+这两个变量结合substr用起来可以非常强大,通过它们可以构造出和$` $& $'等价的值,且能构造出更多匹配结果。例如:

$` == substr($var, 0, $-[0])
$& == substr($var, $-[0], $+[0] - $-[0])
$' == substr($var, $+[0])
$1 == substr($var, $-[1], $+[1] - $-[1])
$2 == substr($var, $-[2], $+[2] - $-[2])
$3 == substr($var, $-[3], $+[3] - $-[3])