简体   繁体   English

带有限制的十进制正则表达式

[英]Regex for Decimal Number with limits

I am trying to write a regex for allowing 3 digit numbers followed by optional decimal, integer part cant be greater than 180 or smaller than -180. 我正在尝试编写一个正则表达式以允许3位数字后接可选的小数,整数部分不能大于180或小于-180。 example of valid enteries are 156.56, 56.778, 9, 6.7.etc etc. So far I came up with this ^(\\+|-)?:180|1[0-7][0-9]|[0-9][0-9]|[0-9]?([\\.][0-9]{1,3})?$ but these seems to match 195.678 too. 有效输入的示例是156.56、56.778、9、6.7.etc等。到目前为止,我想出了这个^(\\+|-)?:180|1[0-7][0-9]|[0-9][0-9]|[0-9]?([\\.][0-9]{1,3})?$但它们似乎也匹配195.678。

Instead of doing that, why not just have two checks? 而不是这样做,为什么不进行两次检查呢? One makes sure that you match the pattern, and the other makes sure that the value is between -180 and 180. 一个确保您匹配该模式,另一个确保该值在-180到180之间。

/-?\d{3}(\.\d{1,3})?/.test(val) && (val <= 180 && val >= -180)

The resulting solution is far easier to understand and maintain, and not to mention, saner :). 最终的解决方案更容易理解和维护,更不用说了:)。

The reason your regex doesn't work is that the ^ and $ don't match across the entire pattern. 您的正则表达式不起作用的原因是^$在整个模式中不匹配。 You have the different conditions in your regex that are separated by | 您的正则表达式中存在由|分隔的不同条件。 . The ^ is associated with the first option, and the $ is associated with the last option. ^与第一个选项关联,而$与最后一个选项关联。 This is easy to see in the following example: 在下面的示例中很容易看到这一点:

Assume you had the regex /^[0-9][0-9]|[0-9]$/ . 假设您使用了正则表达式/^[0-9][0-9]|[0-9]$/ If you tested this against 12345 what would you get? 如果您针对12345了测试,您将得到什么? You might be inclined to say that it would return false , but it actually returns true . 您可能倾向于说它将返回false ,但实际上它返回true This is because there is a valid match! 这是因为存在有效的匹配! The 12 in 12345 will match against ^[0-9][0-9] . 1234512将与^[0-9][0-9]匹配。 So what you're saying is that you want to match against any two numbers at the beginning of the string or against a number at the end of the string. 因此,您要说的是要匹配字符串开头的任何两个数字或字符串结尾的一个数字。 Basically any string that has at least two numbers at the beginning or one number at the end, will match. 基本上任何开头至少有两个数字结尾至少有一个数字的字符串都将匹配。 So 12abc will match, as will abc1 . 所以12abc将匹配,如将abc1

However, if you changed the regex to /^([0-9][0-9]|[0-9])$/ , only one and two-digit numbers will match. 但是,如果将正则表达式更改为/^([0-9][0-9]|[0-9])$/ ,则只能匹配一个数字和两位数字。 This is because the beginning and end-of-string anchors are outside the matching group, meaning the entire group has to match. 这是因为字符串的开始和结束锚都在匹配组之外,这意味着整个组都必须匹配。 This is something that you have to consider when you have conditions in your regex. 当您的正则表达式中有条件时,必须考虑这一点。

EDIT 编辑

Also, Tim points out: 另外,蒂姆指出:

... there is a colon where it shouldn't be: ^(+|-)?:180 matches :180, +:180 or -:180 and nothing else ...冒号不应该是:^(+ |-)?: 180匹配:180,+:180或-:180,其他都没有

Since you introduce the possibility of leading 0's, something like this 由于您介绍了以0开头的可能性,所以像这样
should validate the entire range: 应该验证整个范围:

^(?:\\+|-)?(?: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})?)$

test in Perl 在Perl中测试

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";
}

Output: 输出:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM