我正在尝试编写一个正则表达式,允许3位数字后跟可选的小数,整数部分不能大于180或小于-180。有效企业的例子是156.56,56.778,9,6.7等。
到目前为止,我想出了这个^(\+|-)?:180|1[0-7][0-9]|[0-9][0-9]|[0-9]?([\.][0-9]{1,3})?$
,但这些似乎也与195.678相符。
答案 0 :(得分:4)
为什么不进行两次检查呢?一个确保您匹配模式,另一个确保值在-180和180之间。
/-?\d{3}(\.\d{1,3})?/.test(val) && (val <= 180 && val >= -180)
最终的解决方案更易于理解和维护,更不用说saner :)。
正则表达式不起作用的原因是^
和$
在整个模式中不匹配。您的正则表达式中有不同的条件,由|
分隔。 ^
与第一个选项相关联,$
与最后一个选项相关联。这在以下示例中很容易看到:
假设你有正则表达式/^[0-9][0-9]|[0-9]$/
。如果您针对12345
对此进行了测试,您会得到什么?您可能倾向于说它会返回false
,但它实际上会返回true
。这是因为有一个有效的匹配! 12
中的12345
将与^[0-9][0-9]
匹配。所以你要说的是你要匹配字符串开头的任何两个数字或字符串末尾的数字。基本上任何字符串在开头或一端至少有两个数字匹配。因此12abc
将匹配,abc1
也将匹配。
但是,如果您将正则表达式更改为/^([0-9][0-9]|[0-9])$/
,则只有一位和两位数字匹配。这是因为字符串的起始和结束锚定在匹配组之外,这意味着整个组必须匹配。当你的正则表达式有条件时,你必须考虑这一点。
修改强>
此外,蒂姆指出:
...有一个冒号,它不应该是:^(+ | - )?:180匹配:180,+:180或 - :180,没有别的
答案 1 :(得分:0)
既然你引入了领先0的可能性,就像这样 应验证整个范围:
^(?:\+|-)?(?:180(?:\.0{0,3})?|(?:0{1,3}|0{0,2}[1-9]|0?[1-9][0-9]|1[0-7][0-9])(?:\.[0-9]{1,3})?)$
测试
use strict;
use warnings;
my $regex = qr/
^
(?:\+|-)?
(?:
180 (?:\.0{0,3})?
|
(?:
0{1,3}
|
0{0,2}[1-9]
|
0?[1-9][0-9]
|
1[0-7][0-9]
)
(?:\.[0-9]{1,3})?
)
$
/x;
for ('000' .. '180')
{
my $num;
$num = -1 * $_;
if ( $num =~ /$regex/) { print "$num\t" }
else { print "($num failed)\t" }
$num = 1 * $_;
if ( $num =~ /$regex/) { print "$num\t" }
else { print "($num failed)\t" }
$num = '+' . $_ . ".$_";
if ( $num =~ /$regex/) { print "$num\t" }
else { print "($num failed)\t" }
$num = '-' . $_ . ".$_";
if ( $num =~ /$regex/) { print "$num\t" }
else { print "($num failed)\t" }
print "\n";
}
输出:
0 0 +000.000 -000.000
-1 1 +001.001 -001.001
-2 2 +002.002 -002.002
-3 3 +003.003 -003.003
-4 4 +004.004 -004.004
-5 5 +005.005 -005.005
-6 6 +006.006 -006.006
-7 7 +007.007 -007.007
-8 8 +008.008 -008.008
-9 9 +009.009 -009.009
-10 10 +010.010 -010.010
-11 11 +011.011 -011.011
-12 12 +012.012 -012.012
-13 13 +013.013 -013.013
-14 14 +014.014 -014.014
-15 15 +015.015 -015.015
-16 16 +016.016 -016.016
-17 17 +017.017 -017.017
-18 18 +018.018 -018.018
-19 19 +019.019 -019.019
-20 20 +020.020 -020.020
-21 21 +021.021 -021.021
-22 22 +022.022 -022.022
<snipped>
-172 172 +172.172 -172.172
-173 173 +173.173 -173.173
-174 174 +174.174 -174.174
-175 175 +175.175 -175.175
-176 176 +176.176 -176.176
-177 177 +177.177 -177.177
-178 178 +178.178 -178.178
-179 179 +179.179 -179.179
-180 180 (+180.180 failed) (-180.180 failed)