用regex验证32位整数

时间:2012-10-10 05:11:19

标签: perl

我正在尝试提出一个匹配任何非32位整数的正则表达式。我的最终目标是匹配不符合以下格式的行

Integer\tInteger\tInteger\tInteger\tInteger\tInteger\tInteger

(7个32位整数和每个整数之间的1个选项卡)

到目前为止,我已经提出了这个

#!/usr/bin/perl -w
use strict;
while ( my $line = <> ) {

    if ( $line =~ /^(429496729[0-6]|42949672[0-8]\d|4294967[01]\d{2}|429496[0-6]\d{3}|42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}|4[01]\d{8}|[1-3]\d{9}|[1-9]\d{8}|[1-9]\d{7}|[1-9]\d{6}|[1-9]\d{5}|[1-9]\d{4}|[1-9]\d{3}|[1-9]\d{2}|[1-9]\d|\d)$/ ) {

        print "Match at line $.\n";
        print "$line"
    }

}

但我甚至无法达到将正则表达式匹配为32位数字的第一步(一旦我解决了这个问题,我就可以解决这些问题,就像他们需要的那样)

我是以正确的方式解决这个问题吗?有什么想法吗?

3 个答案:

答案 0 :(得分:6)

  

我是否以正确的方式解决了这个问题?

假设确实需要验证,我的第一种方法是拆分选项卡,检查字段数,检查每个字段但不使用正则表达式。在正则表达式中进行范围检查是愚蠢的! (使用sprintf填充然后进行字符串比较可以解决溢出问题。)

其他问题:

  • \d匹配的不仅仅是0-9。如果您只想匹配0-9,请使用/\d/a/[0-9]/
  • 负数怎么样? 32位整数也可用于存储2147483647 ..- 2147483648。
  • 前导零和领先的正负号怎么样?
  • 千分隔符怎么样?
  • 10.0是整数吗?从数学上讲,它是。 Perl还会将其存储为整数。

答案 1 :(得分:2)

我会说不,这是正确的方式 - 非常很难尝试并遵循该正则表达式;虽然可以做到,但请考虑明天是否有意义。或者,如果范围发生变化或需要稍微改变格式,则改变的难度如下:)

以下是我的建议:

  1. 阅读Is it a Number?以了解如何判断某个值是否为数字,如果是,则将其提取为一个数字。也就是说,获取一个真正的数值,而不是一个字符串。如果需要限制“有效”数字,可以在此阶段进行额外检查;不要限制范围,只需格式

  2. 对提取的数字使用简单的范围检查 - 在这种情况下0到2 32 -1之间?

答案 2 :(得分:2)

你可以在正则表达式中完成所有操作,但最好将它们视为数字并使用数学。

# Split it into fields.
my @fields = split /\t/, $line;

# Scan for fields which do not look like integers
# or are outside the unsigned 32 bit integer range
my $valid_line = !grep { /[^0-9]/ || ($_ < 0) || (2**32-1 < $_) } @fields;

关于“什么是32位整数”的其他答案中的所有警告仍然适用。 “+10”有效吗? “10.0”?如果不知道为什么要过滤这些数字,就无法回答这个问题,并根据需要调整逻辑。

只是扔进perl5i插件......

use perl5i::2;
my $valid_line = !grep { $_->is_integer && ($_ < 0) || (2**32-1 < $_) } @fields;