使用正则表达式验证数字范围 [英] Using regular expressions to validate a numeric range
问题描述
我的输入数字是一个整数.但是输入的数字必须在-2055到2055之间,并且我想使用正则表达式对此进行检查.
My input number is an int. But the input number must be in a range from -2055 to 2055 and I want to check this by using regular expression.
那么反正有没有写正则表达式来检查数字是否在(-2055,2055)中呢?
So is there anyway to write a regular expression to check whether a number is in (-2055, 2055) or not ?
使用if语句检查数字是否在范围内更容易.但是我正在写一个解释器,所以我应该使用正则表达式来检查输入的数字
It is easier to use if statement to check whether the number is in range or not. But I'm writing an interpreter so I should use regex to check the input number
推荐答案
使用正则表达式验证数字范围
要明确:简单的if语句就足够了
To be clear: When a simple if statement will suffice
if(num < -2055 || num > 2055) {
throw new IllegalArgumentException("num (" + num + ") must be between -2055 and 2055");
}
不建议使用正则表达式来验证数字范围.
using regular expressions for validating numeric ranges is not recommended.
此外,由于正则表达式会分析字符串,因此必须先将数字转换为字符串,然后才能对其进行测试.当数字恰好已经是字符串时,例如从控制台获取用户输入时,就是一个例外.
In addition, since regular expressions analyze strings, numbers must first be translated to a string before they can be tested. An exception is when the number happens to already be a string, such as when getting user input from the console.
(要确保字符串是开头的数字,可以使用 org.apache.commons.lang3.math. isNumber(s)
)
(To ensure the string is a number to begin with, you could use org.apache.commons.lang3.math.NumberUtils#isNumber(s)
)
尽管如此,弄清楚如何使用正则表达式验证数字范围还是很有趣和有益的.
Despite this, figuring out how to validate number ranges with regular expressions is interesting and instructive.
(此答案中的链接来自堆栈溢出正则表达式常见问题解答.)
一个数字范围
规则:数字必须恰好是15
.
有最简单的范围.与此匹配的正则表达式是
The simplest range there is. A regex to match this is
\b15\b
字边界对于避免匹配8215242
内部的15
是必需的.
Word boundaries are necessary to avoid matching the 15
inside of 8215242
.
两个数字范围
规则:该数字必须在15
和16
之间.这是三个可能的正则表达式:
The rule: The number must be between 15
and 16
. Here are three possible regexes:
\b(15|16)\b
\b1(5|6)\b
\b1[5-6]\b
(或"号是必需的组,但它们可以不捕获:\b(?:15|16)\b
)
(The groups are required for the "or"-ing, but they could be non-capturing: \b(?:15|16)\b
)
数范围已镜像"大约为零
规则:该数字必须在-12
和12
之间.
The rule: The number must be between -12
and 12
.
这是0
到12
的正则表达式,仅用于正数:
Here is a regex for 0
through 12
, positive-only:
\b(\d|1[0-2])\b
自由空间:
\b( //The beginning of a word (or number), followed by either
\d // Any digit 0 through 9
| //Or
1[0-2] // A 1 followed by any digit between 0 and 2.
)\b //The end of a word
使这项工作对正面和负面都像在开始时添加一个可选破折号一样简单:
Making this work for both negative and positive is as simple as adding an optional dash at the start:
-?\b(\d|1[0-2])\b
(这假定破折号前没有不适当的字符.)
(This assumes no inappropriate characters precede the dash.)
要禁止为负数,必须使用负向后看:
(?<!-)\b(\d|1[0-2])\b
不进行查找会导致-11
中的11
匹配. (本文的第一个示例应添加此内容.)
Leaving the lookbehind out would cause the 11
in -11
to match. (The first example in this post should have this added.)
注意:\d
与[0-9]
In order to be compatible with all regex flavors, all \d
-s should be changed to [0-9]
. For example, .NET considers non ASCII numbers, such as those in different languages, as legal values for \d
. Except for in the last example, for brevity, it's left as \d
.
(感谢 @TimPietzcker )
三位数字,除了第一位以外的其他所有数字都等于零
规则:必须在0
和400
之间.
可能的正则表达式:
A possible regex:
(?<!-)\b([1-3]?\d{1,2}|400)\b
自由行:
(?<!-) //Something not preceded by a dash
\b( //Word-start, followed by either
[1-3]? // No digit, or the digit 1, 2, or 3
\d{1,2} // Followed by one or two digits (between 0 and 9)
| //Or
400 // The number 400
)\b //Word-end
永远不应该使用的另一种可能性:
\b(0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255|256|257|258|259|260|261|262|263|264|265|266|267|268|269|270|271|272|273|274|275|276|277|278|279|280|281|282|283|284|285|286|287|288|289|290|291|292|293|294|295|296|297|298|299|300|301|302|303|304|305|306|307|308|309|310|311|312|313|314|315|316|317|318|319|320|321|322|323|324|325|326|327|328|329|330|331|332|333|334|335|336|337|338|339|340|341|342|343|344|345|346|347|348|349|350|351|352|353|354|355|356|357|358|359|360|361|362|363|364|365|366|367|368|369|370|371|372|373|374|375|376|377|378|379|380|381|382|383|384|385|386|387|388|389|390|391|392|393|394|395|396|397|398|399|400)\b
最终示例:四位数字,围绕零镜像,不以零结尾.
规则:必须在-2055
和2055
这是来自stackoverflow上的问题.
正则表达式:
(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2}|(?<!-)0+))\b
自由空间:
( //Capture group for the entire number
-?\b //Optional dash, followed by a word (number) boundary
(?:20 //Followed by "20", which is followed by one of
(?:5[0-5] //50 through 55
| //or
[0-4][0-9]) //00 through 49
| //or
1[0-9]{3} //a one followed by any three digits
| //or
[1-9][0-9]{0,2} //1-9 followed by 0 through 2 of any digit
| //or
(?<!-)0+ //one-or-more zeros *not* preceded by a dash
) //end "or" non-capture group
)\b //End number capture group, followed by a word-bound
(感谢 PlasmaPower 和
(With thanks to PlasmaPower and Casimir et Hippolyte for the debugging assistance.)
最后的笔记
取决于您的身份捕获,很可能所有子-组应分为非捕获组.例如,这:
Depending on what you are capturing, it is likely that all sub-groups should be made into non-capture groups. For example, this:
(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b)
代替此:
-?\b(20(5[0-5]|[0-4][0-9])|1?[0-9]{1,3})\b
示例Java实现
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.math.NumberUtils;
/**
<P>Confirm a user-input number is a valid number by reading a string an testing it is numeric before converting it to an it--this loops until a valid number is provided.</P>
<P>{@code java UserInputNumInRangeWRegex}</P>
**/
public class UserInputNumInRangeWRegex {
public static final void main(String[] ignored) {
int num = -1;
boolean isNum = false;
int iRangeMax = 2055;
//"": Dummy string, to reuse matcher
Matcher mtchrNumNegThrPos = Pattern.compile("(-?\\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2}|(?<!-)0+))\\b").matcher("");
do {
System.out.print("Enter a number between -" + iRangeMax + " and " + iRangeMax + ": ");
String strInput = (new Scanner(System.in)).next();
if(!NumberUtils.isNumber(strInput)) {
System.out.println("Not a number. Try again.");
} else if(!mtchrNumNegThrPos.reset(strInput).matches()) {
System.out.println("Not in range. Try again.");
} else {
//Safe to convert
num = Integer.parseInt(strInput);
isNum = true;
}
} while(!isNum);
System.out.println("Number: " + num);
}
}
输出
[C:\java_code\]java UserInputNumInRangeWRegex
Enter a number between -2055 and 2055: tuhet
Not a number. Try again.
Enter a number between -2055 and 2055: 283837483
Not in range. Try again.
Enter a number between -2055 and 2055: -200000
Not in range. Try again.
Enter a number between -2055 and 2055: -300
Number: -300
此stackoverflow问题的原始答案
这是一个符合您要求的严肃答案.它类似于@PlasmaPower的答案.
This is a serious answer that fits your specifications. It is similar to @PlasmaPower's answer.
(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2}|(?<!-)0+))\b
这篇关于使用正则表达式验证数字范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!