a {0,1} | b {0,1}只匹配'a',为什么?

时间:2013-10-08 21:33:54

标签: regex perl

为什么会这样?我有一个复杂的正则表达式,但这就是让我疯狂的原因。

a|b

匹配单个a或单个b

a+|b+

匹配a系列或b系列。

a{1}|b{1}

匹配两个单字母相同。

但我需要这样做:

a{0,2}|b{0,2}

这个正则表达式只匹配a而不匹配b。这有什么问题?

更有趣的是,如果我将0更改为1,那么它就是{1,2},它会再次开始正确匹配(或更好,正如预期的那样)。

由于现在看来很清楚,我正在添加我的真实例子:

my $launch_regexp = '(\d*)d{0,1}(\d*)(\+{0,2}|-{0,2})(\d*)';
($dice, $fc, $op, $mod) = ($launch =~ /$launch_regexp/);

其中$launch$ARGV[1]相同。

我想要匹配很多东西。例子:

3 (numbers)

d10 (d + numbers)

3d10 (numbers + d + numbers)

3d10+/-5 (numbers + d + numbers + (+|-) + numbers)

3d10++/--5 (numbers + d + numbers + (++|--) + numbers)

我知道我的正则表达式也匹配其他字符串,但现在它适用于+而不适用于-

如果我用{1,2}更改范围,它会将字符串与+和 - 匹配(但我还需要匹配没有这些修饰符的字符串)。

这是在我的机器上使用Perl 5.16.3进行的,我可以在this website上重现它。

2 个答案:

答案 0 :(得分:7)

字符串" b"可以与正则表达式a{0,2}匹配,因为它正确地具有零个实例' a'。它不会被捕获,但它会匹配。

为了匹配'' aa'或者' bb',您需要(aa|bb)?并将整个正则表达式包裹在^$

我认为您对解决方案的要求是:(\d*)d?(\d+)(?:(\+{1,2}|\-{1,2})(\d*))?

答案 1 :(得分:2)

Perl喜欢字符串中最早的匹配而不是其他任何东西。接下来,它更喜欢最早的一系列|替代品(不是最长的,就像一些正则表达式引擎的情况一样)。 因为你的第一个替代品可以不匹配,perl将在字符串的开头处为任何不以a开头的字符串执行此操作。

您可能需要以下内容:

my ($find) = ($string) =~ /^[^ab]*(a{1,2}|b{1,2}|\z)/;