我正在尝试提出一个匹配任何非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位数字的第一步(一旦我解决了这个问题,我就可以解决这些问题,就像他们需要的那样)
我是以正确的方式解决这个问题吗?有什么想法吗?
答案 0 :(得分:6)
我是否以正确的方式解决了这个问题?
假设确实需要验证,我的第一种方法是拆分选项卡,检查字段数,检查每个字段但不使用正则表达式。在正则表达式中进行范围检查是愚蠢的! (使用sprintf填充然后进行字符串比较可以解决溢出问题。)
其他问题:
\d
匹配的不仅仅是0-9。如果您只想匹配0-9,请使用/\d/a
或/[0-9]/
。10.0
是整数吗?从数学上讲,它是。 Perl还会将其存储为整数。答案 1 :(得分:2)
我会说不,这是不正确的方式 - 非常很难尝试并遵循该正则表达式;虽然可以做到,但请考虑明天是否有意义。或者,如果范围发生变化或需要稍微改变格式,则改变的难度如下:)
以下是我的建议:
阅读Is it a Number?以了解如何判断某个值是否为数字,如果是,则将其提取为一个数字。也就是说,获取一个真正的数值,而不是一个字符串。如果需要限制“有效”数字,可以在此阶段进行额外检查;不要限制范围,只需格式。
对提取的数字使用简单的范围检查 - 在这种情况下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;