在Perl中,匹配的正则表达式中有多少组?

时间:2011-11-11 19:09:18

标签: regex perl types capturing-group

我想说出一个数字1和字符串'1'之间的区别。

我想这样做的原因是因为我想确定成功匹配后正则表达式中捕获括号的数量。根据perlop doc,当模式中没有捕获组时,返回列表(1)。因此,如果我得到一个成功的匹配和一个列表(1),那么我无法判断该模式是否没有parens或它有一个paren并且它匹配'1'。如果数字1和字符串'1'之间存在差异,我可以解决这种歧义。

6 个答案:

答案 0 :(得分:6)

您可以使用特殊的@+数组来判断上次成功匹配中有多少个捕获组。 $#+是捕获组的数量。如果那是0,则没有捕获括号。

答案 1 :(得分:2)

例如,按位运算符对字符串和整数的行为有所不同:

~1 = 18446744073709551614

~'1' = Î('1'= 0x31,~'1'= ~0x31 = 0xce ='Î')

#!/usr/bin/perl

($b) = ('1' =~ /(1)/);
print isstring($b) ? "string\n" : "int\n";
($b) = ('1' =~ /1/);
print isstring($b) ? "string\n" : "int\n";

sub isstring() {
    return ($_[0] & ~$_[0]);
}

isstring返回0(作为数字按位运算的结果),这是假的,或“\ 0”(作为按位字符串操作的结果,设置perldoc perlop),这是真的,因为它是非空字符串。

答案 2 :(得分:1)

如果您想知道正则表达式匹配的捕获组的数量,请计算它们。不要看他们返回的值,这似乎是你的问题:

您可以通过查看列表分配的结果来获取计数,该结果将返回列表分配右侧的项目数:

my $count = my @array = $string =~ m/.../g;

如果您不需要保留捕获缓冲区,请指定一个空列表:

my $count = () = $string =~ m/.../g;

或者分两步完成:

my @array = $string =~ m/.../g;
my $count = @array;

您还可以使用我在 Mastering Perl 的第一页中显示的一些技巧来使用@+@-变量。这些数组具有每个捕获缓冲区的起始位置和结束位置。索引0中的值适用于整个模式,索引1中的值适用于$1,依此类推。那么,最后一个索引是捕获缓冲区的总数。请参阅perlvar

答案 3 :(得分:0)

Perl根据需要自动在字符串和数字之间进行转换。在内部,它分别跟踪值。您可以使用Devel :: Peek查看此操作:

use Devel::Peek;
$x = 1;
$y = '1';
Dump($x);
Dump($y);

输出结果为:

SV = IV(0x3073f40) at 0x3073f44
  REFCNT = 1
  FLAGS = (IOK,pIOK)
  IV = 1
SV = PV(0x30698cc) at 0x3073484
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x3079bb4 "1"\0
  CUR = 1
  LEN = 4

请注意,$x的转储具有IV插槽的值,而$y的转储没有,但在PV插槽中具有值。另请注意,仅使用不同上下文中的值可以触发字符串化或nummification并填充其他插槽。例如如果你在偷看价值之前做过$x . ''$y + 0,你就会得到这个:

SV = PVIV(0x2b30b74) at 0x3073f44
  REFCNT = 1
  FLAGS = (IOK,POK,pIOK,pPOK)
  IV = 1
  PV = 0x3079c5c "1"\0
  CUR = 1
  LEN = 4

此时1'1'根本无法区分。

答案 4 :(得分:0)

成功匹配后检查$ 1的定义。逻辑是这样的:

  • 如果列表为空,则模式匹配失败
  • 否则,如果定义了$ 1,则列表包含所有捕获的子字符串
  • 其他比赛成功,但没有捕捉

答案 5 :(得分:-1)

你的问题没有多大意义,但看起来你想知道它们之间的区别:

$a = "foo"; 
@f = $a =~ /foo/; 

$a = "foo1"; 
@f = $a =~ /foo(1)?/; 

因为无论是否进行了捕获,它们都会返回相同的内容。

答案是:不要尝试使用返回的数组。检查$1是否不等于""