当数字以0结尾时,为什么我的正则表达式失败?

时间:2010-04-17 16:53:55

标签: regex perl

这是一个非常基本的正则表达式问题,但由于我似乎无法弄清楚为什么匹配在某些情况下会失败,我想我会发布它以查看是否有其他人可以指出我缺少的东西。< / p>

我正在尝试从表单的字符串中取出2组数字:

12309123098_102938120938120938
1321312_103810312032123
123123123_10983094854905490
38293827_1293120938129308

我正在使用以下代码处理每个字符串:

if($string && $string =~ /^(\d)+_(\d)+$/) {
    if(IsInteger($1) && IsInteger($2)) { print "success ('$1','$2')"; }
    else { print "fail"; }
}

IsInterger()函数如下:

sub IsInteger {
    my $integer = shift;
    if($integer && $integer =~ /^\d+$/) { return 1; }
    return;
}

此功能似乎在大多数时间都有效,但由于某种原因导致以下情况失败:

1287123437_1268098784380
1287123437_1267589971660

关于为什么这些失败而其他人成功的任何想法?在此先感谢您的帮助!

5 个答案:

答案 0 :(得分:3)

因为在第二个字符串的末尾有0(\d)+只在$N变量中放置最后一个匹配,所以字符串"0"等同于false。 / p>

答案 1 :(得分:3)

这是unicornaddict和ZyX答案的附加内容:你想要匹配什么?

如果您尝试匹配“_”左右两侧的序列,则独角兽上瘾者是正确的,您的正则表达式需要为^(\d+)_(\d+)$。此外,你可以完全摆脱第一个限定符和'IsIntrger()`函数 - 你已经知道它是一个整数 - 它匹配(\ d +)

if ($string =~ /^(\d+)_(\d+)$/) {
    print "success ('$1','$2')";
} else {
    print "fail\n";
}

如果您尝试匹配每个数字中的最后一个数字,并想知道它失败的原因,那么这是IsInteger()if($intger &&)中的第一次检查。无论如何它都是多余的(你知道它是一个整数)并且在0上失败,因为正如ZyX所说 - 它的计算结果为假。

但同样适用:

if ($string =~ /^(\d)+_(\d)+$/) {
    print "success ('$1','$2')";
} else {
    print "fail\n";
}

如果输入success ('8','8')

,这将输出12309123098_102938120938120938

答案 2 :(得分:3)

如有疑问,请检查您的正则表达式实际捕获的内容。

use strict;
use warnings;

my @data = (
    '1321312_103810312032123',
    '123123123_10983094854905490',
);

for my $s (@data){
    print "\$1=$1 \$2=$2\n" if $s =~ /^(\d)+_(\d)+$/;
    # Output:
    # $1=2 $2=3
    # $1=3 $2=0
}

您可能打算采用这两种方法中的第二种方法。

(\d)+  # Repeat a regex group 1+ times,
       # capturing only the last instance.

(\d+)  # Capture 1+ digits.

此外,在你的主循环和IsInteger中(考虑到主循环中的初始正则表达似乎是不必要的),你正在测试真理而不是更具体的东西,例如{{1} }或defined。例如,零是一个有效的整数但是错误。

答案 3 :(得分:0)

分组中不应包含+

^(\d+)_(\d+)$代替^(\d)+_(\d)+$

答案 4 :(得分:0)

很多人都对您的正则表达式进行了评论,但您在IsInteger中遇到了问题(您的示例中并不需要这个问题)。当您确实要检查defined时,您检查了“真相”:

sub IsInteger {
    my $integer = shift;
    if( defined $integer && $integer =~ /^\d+$/) { return 1; }
    return;
}

您不需要该子例程中的大部分基础结构:

sub IsInteger {
    defined $_[0] && $_[0] =~ /^\d+$/
}