使用正则表达式验证数字范围

38

我的输入数字是int类型的。但输入数字必须在-2055到2055的范围内,并且我想通过使用正则表达式来检查这一点。

所以有没有办法编写正则表达式来检查数字是否在(-2055, 2055)范围内?

使用if语句检查数字是否在范围内更容易。但我正在编写解释器,所以应该使用正则表达式检查输入数字。


7
为什么要使用正则表达式?使用 <> 运算符不是更容易吗? - ProgramFOX
5
目前所有的正则表达式解决方案都是不完整/错误的。这可能会让你明白为什么正则表达式不是做这项工作的正确工具,特别是如果你后来需要更改范围... - Tim Pietzcker
1
我正在使用OCaml编写一个解释器……如何在不使用正则表达式的情况下验证输入数字是否在范围内? - Trung Nguyen
@aliteralmind:你的愚蠢版本是正确的,另一个版本可能(取决于使用的正则表达式引擎)会匹配不正确,因为例如在.NET中,\d匹配的远不止数字0-9 - Tim Pietzcker
1
可能是正则表达式:数字范围的重复问题。 - Saullo G. P. Castro
显示剩余4条评论
11个回答

95

使用正则表达式验证数字范围

明确一点:当简单的if语句就足够时

if(num < -2055  ||  num > 2055)  {
   throw  new IllegalArgumentException("num (" + num + ") must be between -2055 and 2055");
}

不建议使用正则表达式来验证数字范围。

此外,由于正则表达式分析字符串,因此在测试之前必须先将数字转换为字符串。例外情况是当数字恰好已经是字符串时,例如从控制台获取用户输入时。

(为了确保字符串最初是一个数字,您可以使用org.apache.commons.lang3.math.NumberUtils#isNumber(s))

尽管如此,通过正则表达式来验证数字范围仍然是有趣和有益的。

(本答案中的链接来自Stack Overflow正则表达式FAQ。)

一个数字范围

规则:一个数字必须恰好为15

这是最简单的数字范围。用于匹配它的正则表达式是

\b15\b

单词边界是必要的,以避免匹配8215242中的15

一个两数范围

规则:数字必须在1516之间。以下是三个可能的正则表达式:

\b(15|16)\b
\b1(5|6)\b
\b1[5-6]\b

(组是用于“或”操作的,但它们可以是非捕获组\b(?:15|16)\b)

围绕零对称的数字范围

规则:数字必须在-1212之间。

这是一个适用于 012的正数的正则表达式:

\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

要使这适用于负数和正数,只需在开头添加一个可选的破折号即可:

-?\b(\d|1[0-2])\b

(假设破折号之前没有不适当的字符。)

为了禁止负数,需要使用负向预查

(?<!-)\b(\d|1[0-2])\b

如果省略匹配正则表达式之前的内容,-11 中的 11 也会被匹配。 (本帖子中的第一个示例应添加此内容。)

注意:\d[0-9]

为了与所有正则表达式风格兼容,所有的\d 应该被更改为 [0-9]。例如,.NET 将非 ASCII 数字(如不同语言中的数字)视为 \d 的合法值。除了最后一个示例外,为了简洁起见,它仍然是 \d

(特别感谢@TimPietzcker

三位数,除第一位数字外,其余均为零

规则:必须介于 0400 之间。

可能的正则表达式:

(?<!-)\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

最终示例:四位数字,以零为中心镜像,不以零结尾。

规则:必须在-20552055之间

这是来自stackoverflow上的一个问题

正则表达式:

(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2}|(?<!-)0+))\b

正则表达式可视化

Debuggex演示

自由间隔:

(             //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

(感谢< A HREF =“https://stackoverflow.com/users/3352674/plasmapower”>PlasmaPower和< a href="https://stackoverflow.com/users/2255089/casimir-et-hippolyte">Casimir et Hippolyte提供的调试帮助。)

最后说明

根据您要< A HREF="http://www.regular-expressions.info/brackets.html" rel="noreferrer">捕获的内容,所有子组都应该转换为非捕获组。例如,此示例:

(-?\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的回答类似。

(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2}|(?<!-)0+))\b

正则表达式可视化

Debuggex 演示


3
这是现在一篇博客文章 - aliteralmind
此答案已添加到Stack Overflow正则表达式FAQ,位于“常见验证任务”下。 - aliteralmind
1
既然您已经将1变为可选项,那么您的模式将匹配001(前导零),-0(带符号零),我建议更改备选项的第三个项目并添加新的备选项:(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2})|\b0)\b - Casimir et Hippolyte
1
感谢您的指正,@CasimiretHippolyte。已修复。我稍微修改了一下,添加了一个负回顾以避免匹配在破折号旁边的1个或多个零(而不是完全匹配“-0”)。我还将零的替代方案移动到主要的“或”非捕获组中。 - aliteralmind

15

从不使用它,但它确实有效。 :)

\b(-2055|-2054|-2053|-2052|-2051|-2050|-2049|-2048|-2047|-2046|-2045|-2044|-2043|-2042|-2041|-2040|-2039|-2038|-2037|-2036|-2035|-2034|-2033|-2032|-2031|-2030|-2029|-2028|-2027|-2026|-2025|-2024|-2023|-2022|-2021|-2020|-2019|-2018|-2017|-2016|-2015|-2014|-2013|-2012|-2011|-2010|-2009|-2008|-2007|-2006|-2005|-2004|-2003|-2002|-2001|-2000|-1999|-1998|-1997|-1996|-1995|-1994|-1993|-1992|-1991|-1990|-1989|-1988|-1987|-1986|-1985|-1984|-1983|-1982|-1981|-1980|-1979|-1978|-1977|-1976|-1975|-1974|-1973|-1972|-1971|-1970|-1969|-1968|-1967|-1966|-1965|-1964|-1963|-1962|-1961|-1960|-1959|-1958|-1957|-1956|-1955|-1954|-1953|-1952|-1951|-1950|-1949|-1948|-1947|-1946|-1945|-1944|-1943|-1942|-1941|-1940|-1939|-1938|-1937|-1936|-1935|-1934|-1933|-1932|-1931|-1930|-1929|-1928|-1927|-1926|-1925|-1924|-1923|-1922|-1921|-1920|-1919|-1918|-1917|-1916|-1915|-1914|-1913|-1912|-1911|-1910|-1909|-1908|-1907|-1906|-1905|-1904|-1903|-1902|-1901|-1900|-1899|-1898|-1897|-1896|-1895|-1894|-1893|-1892|-1891|-1890|-1889|-1888|-1887|-1886|-1885|-1884|-1883|-1882|-1881|-1880|-1879|-1878|-1877|-1876|-1875|-1874|-1873|-1872|-1871|-1870|-1869|-1868|-1867|-1866|-1865|-1864|-1863|-1862|-1861|-1860|-1859|-1858|-1857|-1856|-1855|-1854|-1853|-1852|-1851|-1850|-1849|-1848|-1847|-1846|-1845|-1844|-1843|-1842|-1841|-1840|-1839|-1838|-1837|-1836|-1835|-1834|-1833|-1832|-1831|-1830|-1829|-1828|-1827|-1826|-1825|-1824|-1823|-1822|-1821|-1820|-1819|-1818|-1817|-1816|-1815|-1814|-1813|-1812|-1811|-1810|-1809|-1808|-1807|-1806|-1805|-1804|-1803|-1802|-1801|-1800|-1799|-1798|-1797|-1796|-1795|-1794|-1793|-1792|-1791|-1790|-1789|-1788|-1787|-1786|-1785|-1784|-1783|-1782|-1781|-1780|-1779|-1778|-1777|-1776|-1775|-1774|-1773|-1772|-1771|-1770|-1769|-1768|-1767|-1766|-1765|-1764|-1763|-1762|-1761|-1760|-1759|-1758|-1757|-1756|-1755|-1754|-1753|-1752|-1751|-1750|-1749|-1748|-1747|-1746|-1745|-1744|-1743|-1742|-1741|-1740|-1739|-1738|-1737|-1736|-1735|-1734|-1733|-1732|-1731|-1730|-1729|-1728|-1727|-1726|-1725|-1724|-1723|-1722|-1721|-1720|-1719|-1718|-1717|-1716|-1715|-1714|-1713|-1712|-1711|-1710|-1709|-1708|-1707|-1706|-1705|-1704|-1703|-1702|-1701|-1700|-1699|-1698|-1697|-1696|-1695|-1694|-1693|-1692|-1691|-1690|-1689|-1688|-1687|-1686|-1685|-1684|-1683|-1682|-1681|-1680|-1679|-1678|-1677|-1676|-1675|-1674|-1673|-1672|-1671|-1670|-1669|-1668|-1667|-1666|-1665|-1664|-1663|-1662|-1661|-1660|-1659|-1658|-1657|-1656|-1655|-1654|-1653|-1652|-1651|-1650|-1649|-1648|-1647|-1646|-1645|-1644|-1643|-1642|-1641|-1640|-1639|-1638|-1637|-1636|-1635|-1634|-1633|-1632|-1631|-1630|-1629|-1628|-1627|-1626|-1625|-1624|-1623|-1622|-1621|-1620|-1619|-1618|-1617|-1616|-1615|-1614|-1613|-1612|-1611|-1610|-1609|-1608|-1607|-1606|-1605|-1604|-1603|-1602|-1601|-1600|-1599|-1598|-1597|-1596|-1595|-1594|-1593|-1592|-1591|-1590|-1589|-1588|-1587|-1586|-1585|-1584|-1583|-1582|-1581|-1580|-1579|-1578|-1577|-1576|-1575|-1574|-1573|-1572|-1571|-1570|-1569|-1568|-1567|-1566|-1565|-1564|-1563|-1562|-1561|-1560|-1559|-1558|-1557|-1556|-1555|-1554|-1553|-1552|-1551|-1550|-1549|-1548|-1547|-1546|-1545|-1544|-1543|-1542|-1541|-1540|-1539|-1538|-1537|-1536|-1535|-1534|-1533|-1532|-1531|-1530|-1529|-1528|-1527|-1526|-1525|-1524|-1523|-1522|-1521|-1520|-1519|-1518|-1517|-1516|-1515|-1514|-1513|-1512|-1511|-1510|-1509|-1508|-1507|-1506|-1505|-1504|-1503|-1502|-1501|-1500|-1499|-1498|-1497|-1496|-1495|-1494|-1493|-1492|-1491|-1490|-1489|-1488|-1487|-1486|-1485|-1484|-1483|-1482|-1481|-1480|-1479|-1478|-1477|-1476|-1475|-1474|-1473|-1472|-1471|-1470|-1469|-1468|-1467|-1466|-1465|-1464|-1463|-1462|-1461|-1460|-1459|-1458|-1457|-1456|-1455|-1454|-1453|-1452|-1451|-1450|-1449|-1448|-1447|-1446|-1445|-1444|-1443|-1442|-1441|-1440|-1439|-1438|-1437|-1436|-1435|-1434|-1433|-1432|-1431|-1430|-1429|-1428|-1427|-1426|-1425|-1424|-1423|-1422|-1421|-1420|-1419|-1418|-1417|-1416|-1415|-1414|-1413|-1412|-1411|-1410|-1409|-1408|-1407|-1406|-1405|-1404|-1403|-1402|-1401|-1400|-1399|-1398|-1397|-1396|-1395|-1394|-1393|-1392|-1391|-1390|-1389|-1388|-1387|-1386|-1385|-1384|-1383|-1382|-1381|-1380|-1379|-1378|-1377|-1376|-1375|-1374|-1373|-1372|-1371|-1370|-1369|-1368|-1367|-1366|-1365|-1364|-1363|-1362|-1361|-1360|-1359|-1358|-1357|-1356|-1355|-1354|-1353|-1352|-1351|-1350|-1349|-1348|-1347|-1346|-1345|-1344|-1343|-1342|-1341|-1340|-1339|-1338|-1337|-1336|-1335|-1334|-1333|-1332|-1331|-1330|-1329|-1328|-1327|-1326|-1325|-1324|-1323|-1322|-1321|-1320|-1319|-1318|-1317|-1316|-1315|-1314|-1313|-1312|-1311|-1310|-1309|-1308|-1307|-1306|-1305|-1304|-1303|-1302|-1301|-1300|-1299|-1298|-1297|-1296|-1295|-1294|-1293|-1292|-1291|-1290|-1289|-1288|-1287|-1286|-1285|-1284|-1283|-1282|-1281|-1280|-1279|-1278|-1277|-1276|-1275|-1274|-1273|-1272|-1271|-1270|-1269|-1268|-1267|-1266|-1265|-1264|-1263|-1262|-1261|-1260|-1259|-1258|-1257|-1256|-1255|-1254|-1253|-1252|-1251|-1250|-1249|-1248|-1247|-1246|-1245|-1244|-1243|-1242|-1241|-1240|-1239|-1238|-1237|-1236|-1235|-1234|-1233|-1232|-1231|-1230|-1229|-1228|-1227|-1226|-1225|-1224|-1223|-1222|-1221|-1220|-1219|-1218|-1217|-1216|-1215|-1214|-1213|-1212|-1211|-1210|-1209|-1208|-1207|-1206|-1205|-1204|-1203|-1202|-1201|-1200|-1199|-1198|-1197|-1196|-1195|-1194|-1193|-1192|-1191|-1190|-1189|-1188|-1187|-1186|-1185|-1184|-1183|-1182|-1181|-1180|-1179|-1178|-1177|-1176|-1175|-1174|-1173|-1172|-1171|-1170|-1169|-1168|-1167|-1166|-1165|-1164|-1163|-1162|-1161|-1160|-1159|-1158|-1157|-1156|-1155|-1154|-1153|-1152|-1151|-1150|-1149|-1148|-1147|-1146|-1145|-1144|-1143|-1142|-1141|-1140|-1139|-1138|-1137|-1136|-1135|-1134|-1133|-1132|-1131|-1130|-1129|-1128|-1127|-1126|-1125|-1124|-1123|-1122|-1121|-1120|-1119|-1118|-1117|-1116|-1115|-1114|-1113|-1112|-1111|-1110|-1109|-1108|-1107|-1106|-1105|-1104|-1103|-1102|-1101|-1100|-1099|-1098|-1097|-1096|-1095|-1094|-1093|-1092|-1091|-1090|-1089|-1088|-1087|-1086|-1085|-1084|-1083|-1082|-1081|-1080|-1079|-1078|-1077|-1076|-1075|-1074|-1073|-1072|-1071|-1070|-1069|-1068|-1067|-1066|-1065|-1064|-1063|-1062|-1061|-1060|-1059|-1058|-1057|-1056|-1055|-1054|-1053|-1052|-1051|-1050|-1049|-1048|-1047|-1046|-1045|-1044|-1043|-1042|-1041|-1040|-1039|-1038|-1037|-1036|-1035|-1034|-1033|-1032|-1031|-1030|-1029|-1028|-1027|-1026|-1025|-1024|-1023|-1022|-1021|-1020|-1019|-1018|-1017|-1016|-1015|-1014|-1013|-1012|-1011|-1010|-1009|-1008|-1007|-1006|-1005|-1004|-1003|-1002|-1001|-1000|-999|-998|-997|-996|-995|-994|-993|-992|-991|-990|-989|-988|-987|-986|-985|-984|-983|-982|-981|-980|-979|-978|-977|-976|-975|-974|-973|-972|-971|-970|-969|-968|-967|-966|-965|-964|-963|-962|-961|-960|-959|-958|-957|-956|-955|-954|-953|-952|-951|-950|-949|-948|-947|-946|-945|-944|-943|-942|-941|-940|-939|-938|-937|-936|-935|-934|-933|-932|-931|-930|-929|-928|-927|-926|-925|-924|-923|-922|-921|-920|-919|-918|-917|-916|-915|-914|-913|-912|-911|-910|-909|-908|-907|-906|-905|-904|-903|-902|-901|-900|-899|-898|-897|-896|-895|-894|-893|-892|-891|-890|-889|-888|-887|-886|-885|-884|-883|-882|-881|-880|-879|-878|-877|-876|-875|-874|-873|-872|-871|-870|-869|-868|-867|-866|-865|-864|-863|-862|-861|-860|-859|-858|-857|-856|-855|-854|-853|-852|-851|-850|-849|-848|-847|-846|-845|-844|-843|-842|-841|-840|-839|-838|-837|-836|-835|-834|-833|-832|-831|-830|-829|-828|-827|-826|-825|-824|-823|-822|-821|-820|-819|-818|-817|-816|-815|-814|-813|-812|-811|-810|-809|-808|-807|-806|-805|-804|-803|-802|-801|-800|-799|-798|-797|-796|-795|-794|-793|-792|-791|-790|-789|-788|-787|-786|-785|-784|-783|-782|-781|-780|-779|-778|-777|-776|-775|-774|-773|-772|-771|-770|-769|-768|-767|-766|-765|-764|-763|-762|-761|-760|-759|-758|-757|-756|-755|-754|-753|-752|-751|-750|-749|-748|-747|-746|-745|-744|-743|-742|-741|-740|-739|-738|-737|-736|-735|-734|-733|-732|-731|-730|-729|-728|-727|-726|-725|-724|-723|-722|-721|-720|-719|-718|-717|-716|-715|-714|-713|-712|-711|-710|-709|-708|-707|-706|-705|-704|-703|-702|-701|-700|-699|-698|-697|-696|-695|-694|-693|-692|-691|-690|-689|-688|-687|-686|-685|-684|-683|-682|-681|-680|-679|-678|-677|-676|-675|-674|-673|-672|-671|-670|-669|-668|-667|-666|-665|-664|-663|-662|-661|-660|-659|-658|-657|-656|-655|-654|-653|-652|-651|-650|-649|-648|-647|-646|-645|-644|-643|-642|-641|-640|-639|-638|-637|-636|-635|-634|-633|-632|-631|-630|-629|-628|-627|-626|-625|-624|-623|-622|-621|-620|-619|-618|-617|-616|-615|-614|-613|-612|-611|-610|-609|-608|-607|-606|-605|-604|-603|-602|-601|-600|-599|-598|-597|-596|-595|-594|-593|-592|-591|-590|-589|-588|-587|-586|-585|-584|-583|-582|-581|-580|-579|-578|-577|-576|-575|-574|-573|-572|-571|-570|-569|-568|-567|-566|-565|-564|-563|-562|-561|-560|-559|-558|-557|-556|-555|-554|-553|-552|-551|-550|-549|-548|-547|-546|-545|-544|-543|-542|-541|-540|-539|-538|-537|-536|-535|-534|-533|-532|-531|-530|-529|-528|-527|-526|-525|-524|-523|-522|-521|-520|-519|-518|-517|-516|-515|-514|-513|-512|-511|-510|-509|-508|-507|-506|-505|-504|-503|-502|-501|-500|-499|-498|-497|-496|-495|-494|-493|-492|-491|-490|-489|-488|-487|-486|-485|-484|-483|-482|-481|-480|-479|-478|-477|-476|-475|-474|-473|-472|-471|-470|-469|-468|-467|-466|-465|-464|-463|-462|-461|-460|-459|-458|-457|-456|-455|-454|-453|-452|-451|-450|-449|-448|-447|-446|-445|-444|-443|-442|-441|-440|-439|-438|-437|-436|-435|-434|-433|-432|-431|-430|-429|-428|-427|-426|-425|-424|-423|-422|-421|-420|-419|-418|-417|-416|-415|-414|-413|-412|-411|-410|-409|-408|-407|-406|-405|-404|-403|-402|-401|-400|-399|-398|-397|-396|-395|-394|-393|-392|-391|-390|-389|-388|-387|-386|-385|-384|-383|-382|-381|-380|-379|-378|-377|-376|-375|-374|-373|-372|-371|-370|-369|-368|-367|-366|-365|-364|-363|-362|-361|-360|-359|-358|-357|-356|-355|-354|-353|-352|-351|-350|-349|-348|-347|-346|-345|-344|-343|-342|-341|-340|-339|-338|-337|-336|-335|-334|-333|-332|-331|-330|-329|-328|-327|-326|-325|-324|-323|-322|-321|-320|-319|-318|-317|-316|-315|-314|-313|-312|-311|-310|-309|-308|-307|-306|-305|-304|-303|-302|-301|-300|-299|-298|-297|-296|-295|-294|-293|-292|-291|-290|-289|-288|-287|-286|-285|-284|-283|-282|-281|-280|-279|-278|-277|-276|-275|-274|-273|-272|-271|-270|-269|-268|-267|-266|-265|-264|-263|-262|-261|-260|-259|-258|-257|-256|-255|-254|-253|-252|-251|-250|-249|-248|-247|-246|-245|-244|-243|-242|-241|-240|-239|-238|-237|-236|-235|-234|-233|-232|-231|-230|-229|-228|-227|-226|-225|-224|-223|-222|-221|-220|-219|-218|-217|-216|-215|-214|-213|-212|-211|-210|-209|-208|-207|-206|-205|-204|-203|-202|-201|-200|-199|-198|-197|-196|-195|-194|-193|-192|-191|-190|-189|-188|-187|-186|-185|-184|-183|-182|-181|-180|-179|-178|-177|-176|-175|-174|-173|-172|-171|-170|-169|-168|-167|-166|-165|-164|-163|-162|-161|-160|-159|-158|-157|-156|-155|-154|-153|-152|-151|-150|-149|-148|-147|-146|-145|-144|-143|-142|-141|-140|-139|-138|-137|-136|-135|-134|-133|-132|-131|-130|-129|-128|-127|-126|-125|-124|-123|-122|-121|-120|-119|-118|-117|-116|-115|-114|-113|-112|-111|-110|-109|-108|-107|-106|-105|-104|-103|-102|-101|-100|-99|-98|-97|-96|-95|-94|-93|-92|-91|-90|-89|-88|-87|-86|-85|-84|-83|-82|-81|-80|-79|-78|-77|-76|-75|-74|-73|-72|-71|-70|-69|-68|-67|-66|-65|-64|-63|-62|-61|-60|-59|-58|-57|-56|-55|-54|-53|-52|-51|-50|-49|-48|-47|-46|-45|-44|-43|-42|-41|-40|-39|-38|-37|-36|-35|-34|-33|-32|-31|-30|-29|-28|-27|-26|-25|-24|-23|-22|-21|-20|-19|-18|-17|-16|-15|-14|-13|-12|-11|-10|-9|-8|-7|-6|-5|-4|-3|-2|-1|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|401|402|403|404|405|406|407|408|409|410|411|412|413|414|415|416|417|418|419|420|421|422|423|424|425|426|427|428|429|430|431|432|433|434|435|436|437|438|439|440|441|442|443|444|445|446|447|448|449|450|451|452|453|454|455|456|457|458|459|460|461|462|463|464|465|466|467|468|469|470|471|472|473|474|475|476|477|478|479|480|481|482|483|484|485|486|487|488|489|490|491|492|493|494|495|496|497|498|499|500|501|502|503|504|505|506|507|508|509|510|511|512|513|514|515|516|517|518|519|520|521|522|523|524|525|526|527|528|529|530|531|532|533|534|535|536|537|538|539|540|541|542|543|544|545|546|547|548|549|550|551|552|553|554|555|556|557|558|559|560|561|562|563|564|565|566|567|568|569|570|571|572|573|574|575|576|577|578|579|580|581|582|583|584|585|586|587|588|589|590|591|592|593|594|595|596|597|598|599|600|601|602|603|604|605|606|607|608|609|610|611|612|613|614|615|616|617|618|619|620|621|622|623|624|625|626|627|628|629|630|631|632|633|634|635|636|637|638|639|640|641|642|643|644|645|646|647|648|649|650|651|652|653|654|655|656|657|658|659|660|661|662|663|664|665|666|667|668|669|670|671|672|673|674|675|676|677|678|679|680|681|682|683|684|685|686|687|688|689|690|691|692|693|694|695|696|697|698|699|700|701|702|703|704|705|706|707|708|709|710|711|712|713|714|715|716|717|718|719|720|721|722|723|724|725|726|727|728|729|730|731|732|733|734|735|736|737|738|739|740|741|742|743|744|745|746|747|748|749|750|751|752|753|754|755|756|757|758|759|760|761|762|763|764|765|766|767|768|769|770|771|772|773|774|775|776|777|778|779|780|781|782|783|784|785|786|787|788|789|790|791|792|793|794|795|796|797|798|799|800|801|802|803|804|805|806|807|808|809|810|811|812|813|814|815|816|817|818|819|820|821|822|823|824|825|826|827|828|829|830|831|832|833|834|835|836|837|838|839|840|841|842|843|844|845|846|847|848|849|850|851|852|853|854|855|856|857|858|859|860|861|862|863|864|865|866|867|868|869|870|871|872|873|874|875|876|877|878|879|880|881|882|883|884|885|886|887|888|889|890|891|892|893|894|895|896|897|898|899|900|901|902|903|904|905|906|907|908|909|910|911|912|913|914|915|916|917|918|919|920|921|922|923|924|925|926|927|928|929|930|931|932|933|934|935|936|937|938|939|940|941|942|943|944|945|946|947|948|949|950|951|952|953|954|955|956|957|958|959|960|961|962|963|964|965|966|967|968|969|970|971|972|973|974|975|976|977|978|979|980|981|982|983|984|985|986|987|988|989|990|991|992|993|994|995|996|997|998|999|1000|1001|1002|1003|1004|1005|1006|1007|1008|1009|1010|1011|1012|1013|1014|1015|1016|1017|1018|1019|1020|1021|1022|1023|1024|1025|1026|1027|1028|1029|1030|1031|1032|1033|1034|1035|1036|1037|1038|1039|1040|1041|1042|1043|1044|1045|1046|1047|1048|1049|1050|1051|1052|1053|1054|1055|1056|1057|1058|1059|1060|1061|1062|1063|1064|1065|1066|1067|1068|1069|1070|1071|1072|1073|1074|1075|1076|1077|1078|1079|1080|1081|1082|1083|1084|1085|1086|1087|1088|1089|1090|1091|1092|1093|1094|1095|1096|1097|1098|1099|1100|1101|1102|1103|1104|1105|1106|1107|1108|1109|1110|1111|1112|1113|1114|1115|1116|1117|1118|1119|1120|1121|1122|1123|1124|1125|1126|1127|1128|1129|1130|1131|1132|1133|1134|1135|1136|1137|1138|1139|1140|1141|1142|1143|1144|1145|1146|1147|1148|1149|1150|1151|1152|1153|1154|1155|1156|1157|1158|1159|1160|1161|1162|1163|1164|1165|1166|1167|1168|1169|1170|1171|1172|1173|1174|1175|1176|1177|1178|1179|1180|1181|1182|1183|1184|1185|1186|1187|1188|1189|1190|1191|1192|1193|1194|1195|1196|1197|1198|1199|1200|1201|1202|1203|1204|1205|1206|1207|1208|1209|1210|1211|1212|1213|1214|1215|1216|1217|1218|1219|1220|1221|1222|1223|1224|1225|1226|1227|1228|1229|1230|1231|1232|1233|1234|1235|1236|1237|1238|1239|1240|1241|1242|1243|1244|1245|1246|1247|1248|1249|1250|1251|1252|1253|1254|1255|1256|1257|1258|1259|1260|1261|1262|1263|1264|1265|1266|1267|1268|1269|1270|1271|1272|1273|1274|1275|1276|1277|1278|1279|1280|1281|1282|1283|1284|1285|1286|1287|1288|1289|1290|1291|1292|1293|1294|1295|1296|1297|1298|1299|1300|1301|1302|1303|1304|1305|1306|1307|1308|1309|1310|1311|1312|1313|1314|1315|1316|1317|1318|1319|1320|1321|1322|1323|1324|1325|1326|1327|1328|1329|1330|1331|1332|1333|1334|1335|1336|1337|1338|1339|1340|1341|1342|1343|1344|1345|1346|1347|1348|1349|1350|1351|1352|1353|1354|1355|1356|1357|1358|1359|1360|1361|1362|1363|1364|1365|1366|1367|1368|1369|1370|1371|1372|1373|1374|1375|1376|1377|1378|1379|1380|1381|1382|1383|1384|1385|1386|1387|1388|1389|1390|1391|1392|1393|1394|1395|1396|1397|1398|1399|1400|1401|1402|1403|1404|1405|1406|1407|1408|1409|1410|1411|1412|1413|1414|1415|1416|1417|1418|1419|1420|1421|1422|1423|1424|1425|1426|1427|1428|1429|1430|1431|1432|1433|1434|1435|1436|1437|1438|1439|1440|1441|1442|1443|1444|1445|1446|1447|1448|1449|1450|1451|1452|1453|1454|1455|1456|1457|1458|1459|1460|1461|1462|1463|1464|1465|1466|1467|1468|1469|1470|1471|1472|1473|1474|1475|1476|1477|1478|1479|1480|1481|1482|1483|1484|1485|1486|1487|1488|1489|1490|1491|1492|1493|1494|1495|1496|1497|1498|1499|1500|1501|1502|1503|1504|1505|1506|1507|1508|1509|1510|1511|1512|1513|1514|1515|1516|1517|1518|1519|1520|1521|1522|1523|1524|1525|1526|1527|1528|1529|1530|1531|1532|1533|1534|1535|1536|1537|1538|1539|1540|1541|1542|1543|1544|1545|1546|1547|1548|1549|1550|1551|1552|1553|1554|1555|1556|1557|1558|1559|1560|1561|1562|1563|1564|1565|1566|1567|1568|1569|1570|1571|1572|1573|1574|1575|1576|1577|1578|1579|1580|1581|1582|1583|1584|1585|1586|1587|1588|1589|1590|1591|1592|1593|1594|1595|1596|1597|1598|1599|1600|1601|1602|1603|1604|1605|1606|1607|1608|1609|1610|1611|1612|1613|1614|1615|1616|1617|1618|1619|1620|1621|1622|1623|1624|1625|1626|1627|1628|1629|1630|1631|1632|1633|1634|1635|1636|1637|1638|1639|1640|1641|1642|1643|1644|1645|1646|1647|1648|1649|1650|1651|1652|1653|1654|1655|1656|1657|1658|1659|1660|1661|1662|1663|1664|1665|1666|1667|1668|1669|1670|1671|1672|1673|1674|1675|1676|1677|1678|1679|1680|1681|1682|1683|1684|1685|1686|1687|1688|1689|1690|1691|1692|1693|1694|1695|1696|1697|1698|1699|1700|1701|1702|1703|1704|1705|1706|1707|1708|1709|1710|1711|1712|1713|1714|1715|1716|1717|1718|1719|1720|1721|1722|1723|1724|1725|1726|1727|1728|1729|1730|1731|1732|1733|1734|1735|1736|1737|1738|1739|1740|1741|1742|1743|1744|1745|1746|1747|1748|1749|1750|1751|1752|1753|1754|1755|1756|1757|1758|1759|1760|1761|1762|1763|1764|1765|1766|1767|1768|1769|1770|1771|1772|1773|1774|1775|1776|1777|1778|1779|1780|1781|1782|1783|1784|1785|1786|1787|1788|1789|1790|1791|1792|1793|1794|1795|1796|1797|1798|1799|1800|1801|1802|1803|1804|1805|1806|1807|1808|1809|1810|1811|1812|1813|1814|1815|1816|1817|1818|1819|1820|1821|1822|1823|1824|1825|1826|1827|1828|1829|1830|1831|1832|1833|1834|1835|1836|1837|1838|1839|1840|1841|1842|1843|1844|1845|1846|1847|1848|1849|1850|1851|1852|1853|1854|1855|1856|1857|1858|1859|1860|1861|1862|1863|1864|1865|1866|1867|1868|1869|1870|1871|1872|1873|1874|1875|1876|1877|1878|1879|1880|1881|1882|1883|1884|1885|1886|1887|1888|1889|1890|1891|1892|1893|1894|1895|1896|1897|1898|1899|1900|1901|1902|1903|1904|1905|1906|1907|1908|1909|1910|1911|1912|1913|1914|1915|1916|1917|1918|1919|1920|1921|1922|1923|1924|1925|1926|1927|1928|1929|1930|1931|1932|1933|1934|1935|1936|1937|1938|1939|1940|1941|1942|1943|1944|1945|1946|1947|1948|1949|1950|1951|1952|1953|1954|1955|1956|1957|1958|1959|1960|1961|1962|1963|1964|1965|1966|1967|1968|1969|1970|1971|1972|1973|1974|1975|1976|1977|1978|1979|1980|1981|1982|1983|1984|1985|1986|1987|1988|1989|1990|1991|1992|1993|1994|1995|1996|1997|1998|1999|2000|2001|2002|2003|2004|2005|2006|2007|2008|2009|2010|2011|2012|2013|2014|2015|2016|2017|2018|2019|2020|2021|2022|2023|2024|2025|2026|2027|2028|2029|2030|2031|2032|2033|2034|2035|2036|2037|2038|2039|2040|2041|2042|2043|2044|2045|2046|2047|2048|2049|2050|2051|2052|2053|2054|2055)\b

末尾多了一个 |,这也会导致速度变慢。不过,这是我最初回答问题的想法 - 制作一个计算机程序来完成它! - PlasmaPower
由于正则表达式前面的单词边界,这与任何负数都不匹配。 - Toto

6

1
2018年4月:更新了链接到http://gamon.webfactional.com/regexnumericrangegenerator - Wiktor Stribiżew
@WiktorStribiżew 更新的链接也失效了。 - Muhammedogz
1
@muhammedoğuz 您可以使用ROS Regex Numeric Range Generator。此外,这是我的fiddle - Wiktor Stribiżew

5

分析问题

如果你“必须”使用正则表达式,那么可以通过分析接受的排列方式来解决问题。

“范围从-2055到2055”可以表示为:

  • 一个可选的-
  • 可选的前导零
  • 后跟0到2055之间的数字

“0到2055之间的数字”可以是有限数量的特定排列之一:

  • 一个数字(0-9)
  • 两个数字(10-99)
  • 三个数字(100-999)
  • 以1开头的四位数(1000-1999)
  • 以20开头的四位数(2000-204*9)
  • 以205开头的四位数(2050-2055*)

请注意,对于此正则表达式,没有必要区分“0-9”和“1-9”的范围,并且只有最后两个范围对接受的数字/字符的范围有任何限制(用星号标记)。

编写组件正则表达式

每个上述组件部分都很容易单独表示为正则表达式:

  • -?
  • 0*
    • [0-9]
    • [0-9][0-9]
    • [0-9][0-9][0-9]
    • 1[0-9][0-9][0-9]
    • 20[0-4][0-9]
    • 205[0-5]

将表达式组合起来

整个匹配的相关表达式应为:

-?0*([0-9]|[0-9][0-9]|[0-9][0-9][0-9]|1[0-9][0-9][0-9]|20[0-4][0-9]|205[0-5])

或稍微简洁一些:
-?0*([0-9]{1,3}|1[0-9]{3}|20[0-4][0-9]|205[0-5])

假设输入只包含"数字",那么最终的正则表达式如下:
^-?0*([0-9]{1,3}|1[0-9]{3}|20[0-4][0-9]|205[0-5])$

如果需要允许前导加号,那么代码如下所示:

^[-+]?0*([0-9]{1,3}|1[0-9]{3}|20[0-4][0-9]|205[0-5])$

这是一个js fiddle演示,展示了哪些内容能通过最后一个正则表达式,哪些不能通过。


5

有这么多答案,但是没有人在评论中关心或阅读发问者的附加问题?

我正在用OCaml编写解释器....如何在不使用正则表达式的情况下验证输入数字是否在范围内? - Trung Nguyen Mar 2 at 17:30

正如许多答案所指出的那样,在这种情况下使用正则表达式是可怕的。让我们想想其他在OCaml中的解决方案!虽然我已经很久没有用OCaml了,但是查找一些构造后我能够将它组合起来:

let isInRange i = 
  not (i < -2055 or i > 2055);;
    
let isIntAndInRange s = 
  try
    let i = int_of_string s in
    not (i < -2055 or i > 2055)
  with 
    Failure "int_of_string" -> false;;
    
let () = print_string "type a number: " in
let s = read_line () in
isIntAndInRange s

如果有任何不清楚的地方,请查阅其语法,类型转换函数异常处理输入输出函数
用户输入部分仅用于演示。在那里使用read_int函数可能更加方便。但处理异常的基本概念保持不变。
从OCaml 4.02开始,可以通过匹配来简化异常处理。
let isIntAndInRange s =
  match int_of_string s with
  | i when i >= -2055 && i <= 2055 -> true
  | _ 
  | exception Failure _ -> false

1
可能是因为评论不是“问题”,所以阅读评论并不是必要的。无论如何,在OP使用的(尚未标记和在问题中未提及的)语言中,这似乎是一个合适的解决方案,所以点赞。 - AD7six

4
作为对aliteralmind所提供的优秀表达的替代方法,这里提供一个更加冗长的方法,以便了解另一种方法可能是什么样子(以及不应该做什么)。
这是一个有趣的练习,因为你可以考虑到两种不同的方法:大致上,你可以:
1. 按4位数字,然后3位数字等进行匹配。 2. 或者按千位数字、百位数字等进行匹配。
没有尝试过,你怎么知道哪个是最好的呢?事实证明,第一种方法(aliteralmind的答案)要经济得多。
下面,我将在“自由空间模式”下给出正则表达式,允许在正则表达式中使用注释,以便您可以轻松理解它的含义。但并非所有正则表达式引擎都支持自由空间模式,因此在我们开始有趣的部分之前,这里是一个单行的正则表达式。
请注意,您的问题提到了从-2055到2055的数字。我假设您想匹配“正常数字”,而不包括前导零。这意味着正则表达式将匹配999,但不匹配0999。如果您想使用前导零,请告诉我,这很容易修改。
此外,如果您正在utf-8模式下匹配,则应将`\d`替换为`[0-9]`。这是更常见的形式。
正则表达式作为单行:
^(?!-0$)-?(?:(?=\d{4}$)[12])?(?:(?=\d{3}$)(?:(?:(?<=^)|(?<=^-)|(?<=1)|(?<=-1))\d|(?:(?<=2)|(?<=-2))0))?(?:(?=\d{2}$)(?:(?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|(?<=^\d{2})(?<!20)|(?<=^-\d{2})(?<!-20))\d|(?:(?<=20)|(?<=-20))[0-5]))?(?:(?=\d$)(?:(?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|(?<=^\d{2})|(?<=^-\d{2})|(?<=^\d{3})(?<!205)|(?<=^-\d{3})(?<!-205))\d|(?:(?<=205)|(?<=-205))[0-5]))$
自由空格模式下的正则表达式
(?x)                # free-spacing mode
^                   # anchor at beginning of string.
(?!-0$)-?           # optional minus sign, but not for -0

(?:                 # OPTIONAL THOUSANDS DIGIT
(?=\d{4}$)[12]      # assert that the number is 4-digit long, match 1 or 2
)?                  # end optional thousands digit


(?:                 # OPTIONAL HUNDREDS DIGIT
(?=\d{3}$)          # assert that there are three digits left
(?:                 # non-capturing group
  (?:(?<=^)|(?<=^-)|(?<=1)|(?<=-1))\d    # if preceding chars are 1, -1 or head of string: value can be any digit
  |                      # or
  (?:(?<=2)|(?<=-2))0                # if preceding chars are 2 or -2: value must be 0
)                   # close non-capturing group
)?                  # end optional hundreds digits

(?:             # OPTIONAL TENS DIGIT
(?=\d{2}$)      # assert that there are two digits left
(?:             # start non-capturing group

                # if preceding char is head of string, single digit,
                # or two digits that are not 20
                # (with or without a minus)
                # value can be any digit
  (?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|
     (?<=^\d{2})(?<!20)|(?<=^-\d{2})(?<!-20))\d  
|               # or
(?:(?<=20)|(?<=-20))[0-5]  # if preceding chars are 20 or -20: value can be from 0 to 5

)               # end non-capturing group
)?              # close optional tens digits

(?:             # FINAL DIGIT (non optional)
(?=\d$)         # assert that there is only one digit left
(?:             # start non-capturing group

                # if preceding char is head of string, single digit, 
                # two digits, or three digits that are not 205
                # (with or without a minus)
                # value can be any digit
  (?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|
      (?<=^\d{2})|(?<=^-\d{2})|
      (?<=^\d{3})(?<!205)|(?<=^-\d{3})(?<!-205))
      \d
  |             # or
  (?:(?<=205)|(?<=-205))[0-5] # if preceding chars are 205 or -205: value can be from 0 to 5
)               # end non-capturing group
)               # end final digit
$

一系列测试

这些测试尝试匹配的数字范围从-100000到100000。它们会产生以下输出:

Successful test: matches from -2055 to 2055
Successful test: NO matches from -100000 to -2056
Successful test: NO matches from 2056 to 100000

以下是代码:

<?php
$regex="~^(?!-0$)-?(?:(?=\d{4}$)[12])?(?:(?=\d{3}$)(?:(?:(?<=^)|(?<=^-)|(?<=1)|(?<=-1))\d|(?:(?<=2)|(?<=-2))0))?(?:(?=\d{2}$)(?:(?:(?<=20)|(?<=-20))[0-5]|(?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|(?<=^\d{2})(?<!20)|(?<=^-\d{2})(?<!-20))\d))?(?:(?=\d$)(?:(?:(?<=205)|(?<=-205))[0-5]|(?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|(?<=^\d{2})|(?<=^-\d{2})|(?<=^\d{3})(?<!205)|(?<=^-\d{3})(?<!-205))\d))$~";

// Test 1
$success="Successful test: matches from -2055 to 2055";
for($i=-2055;$i<=2055;$i++) {
$chari = sprintf("%d",$i);
if (! preg_match($regex,$chari)) {
    $success="Failed test: matches from -2055 to 2055";
    echo $chari.": No Match!<br />";
    }
}
echo $success."<br />";

// Test 2
$success="Successful test: NO matches from -100000 to -2056";
for($i=-100000;$i<=-2056;$i++) {
$chari = sprintf("%d",$i);
if (preg_match($regex,$chari)) {
    $success="Failed test: NO matches from -100000 to -2056";
    echo $chari.": Match!<br />";
    }
}
echo $success."<br />";

// Test 3
$success="Successful test: NO matches from 2056 to 100000";
for($i=2056;$i<=100000;$i++) {
$chari = sprintf("%d",$i);
if (preg_match($regex,$chari)) {
    $success="Failed test: NO matches from 2056 to 100000";
    echo $chari.": Match!<br />";
    }
}
echo $success."<br />";

?>

速度测试

这是我的简单速度测试的输出结果,范围从-1M到+1M。正如Casimir所指出的,如果aliteralmind的表达式被锚定,而不是变慢25%,它将变快25%!

zx81: 3.796217918396
aliteralmind: 3.9922280311584
difference: 5.1632998151294 percent longer

这里是测试代码:
$regex="~(?x)^(?!-0$)-?(?:(?=\d{4}$)[12])?(?:(?=\d{3}$)(?:(?:(?<=^)|(?<=^-)|(?<=1)|(?<=-1))\d|(?:(?<=2)|(?<=-2))0))?(?:(?=\d{2}$)(?:(?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|(?<=^\d{2})(?<!20)|(?<=^-\d{2})(?<!-20))\d|(?:(?<=20)|(?<=-20))[0-5]))?(?:(?=\d$)(?:(?:(?<=^)|(?<=^-)|(?<=^\d)|(?<=^-\d)|(?<=^\d{2})|(?<=^-\d{2})|(?<=^\d{3})(?<!205)|(?<=^-\d{3})(?<!-205))\d|(?:(?<=205)|(?<=-205))[0-5]))$~";

$regex2 = "~(-?\b(?:20(?:5[0-5]|[0-4][0-9])|1[0-9]{3}|[1-9][0-9]{0,2}|(?<!-)0+))\b~";

$start=microtime(TRUE);
for ($i=-1000000;$i<1000000;$i++) preg_match($regex,$i);
$zxend=microtime(TRUE);
for ($i=-1000000;$i<1000000;$i++) preg_match($regex2,$i);
$alitend=microtime(TRUE);
$zx81 = $zxend-$start;
$alit = $alitend-$zxend;
$diff = 100*($alit-$zx81)/$zx81;
echo "zx81: ".$zx81."<br />";
echo "aliteralmind: ".$alit."<br />";
echo "difference: ".$diff." percent longer<br />";

你的模式似乎更快,只是因为你假设数字在字符串的开头。但是原帖并没有明确说明。如果你在alitermind模式中添加锚点“^”,你会看到非常不同的结果。将锚点添加到模式中是第一个优化点。 - Casimir et Hippolyte
@CasimiretHippolyte,谢谢,我拥有那本书。你说得对: 使用插入符锚定符号 ^,相同的测试表明aliteralmind的正则表达式速度快25%。 - zx81
一个好的任务是阅读简单的模式,并查看正则表达式引擎必须执行的步骤数(在开始时使用regex101(有点小问题)或regexbuddy,之后不用)。 - Casimir et Hippolyte
看到这样一个不同的正则表达式实现了相同的功能,真是有趣。+1。 - aliteralmind
@literalmind 是的,当你试图死板地匹配成千上万、数百等数量时,与从左到右的方法相比会产生有趣的结果。 - zx81
显示剩余3条评论

3

为什么只使用正则表达式来检查数字?

int n = -2000;

if(n >= -2055 && n <= 2055)
//Do something
else
//Do something else

1
也许你正在访问一些内容,无法编写代码但可以使用正则表达式,例如Postman、VS Code,在这种情况下,如果你想搜索一个整数,那么正则表达式就是唯一的选择。 - Mahesh Jamdade
正如@maheshmnj上面的评论所述。尝试解析一个命令,该命令从1到64中取值,在只接受正则表达式的语法突出显示器中。 - AgentM

3

试试这个:

\-?\b0*(205[0-5]|20[0-4]\d|1?\d{3}|\d{1,2})\b

是的,请看我的最后一个正则表达式 - \-?\d{1,2}(糟糕) - PlasmaPower
现在它不允许从“-99”到“99”的整个范围。但它仍然允许“0999”... - Tim Pietzcker
好的,以0开头的数字不再起作用。如果需要,我可以将其添加回去。 - PlasmaPower
已添加对以0开头的数字的支持。希望这次能够正常工作。 - PlasmaPower
1
现在只希望OP不打算在.NET引擎中使用该正则表达式,否则它将匹配 1२۱۲ 和其他使用非ASCII数字的数字...要习惯这一点,正则表达式并不是在这里使用的工具。 - Tim Pietzcker

1
尝试使用一个非常简单的正则表达式。
^([-0][0-1][0-9][0-9][0-9])$|^([-0]20[0-4][0-9])$|^([-0]205[0-5])$

可视化表示

enter image description here

这很容易理解。

  • 第1组[-0][0-1][0-9][0-9][0-9]将覆盖[-1999, 1999]的值
  • 第2组[-0]20[0-4][0-9]将覆盖[-2000,-2049][2000,2049]的值
  • 第3组[-0]205[0-5]将覆盖[-2050, -2055][2050, 2055]的值

String.format("%05d", number)在这里做得非常好吗?

示例代码:(阅读内联注释以获得更多清晰度。)

int[] numbers = new int[] { -10002, -3000, -2056, -2055, -2000, -1999, -20, 
                            -1,  0, 1, 260, 1999, 2000, 2046, 2055, 2056, 2955, 
                             3000, 10002, 123456 };

//valid range -2055 to 2055 inclusive

Pattern p = Pattern.compile("^([-0][0-1][0-9][0-9][0-9])$|^([-0]20[0-4][0-9])$|^([-0]205[0-5])$");

for (int number : numbers) {
    String string = String.format("%05d", number);
    Matcher m = p.matcher(string);

    if (m.find()) {
        System.out.println(number + " is in range.");
    } else {
        System.out.println(number + " is not in range.");
    }
}

输出:

-10002 is not in range.
-3000 is not in range.
-2056 is not in range.
-2055 is in range.
-2000 is in range.
-1999 is in range.
-20 is in range.
-1 is in range.
0 is in range.
1 is in range.
260 is in range.
1999 is in range.
2000 is in range.
2046 is in range.
2055 is in range.
2056 is not in range.
2955 is not in range.
3000 is not in range.
10002 is not in range.
123456 is not in range.

你的正则表达式并不适用于所有情况。例如:2046 应该在范围内。 - SF Lee
@SFLee 让我来检查一下。感谢您的注意。 - Braj
顺便问一下,我对你的[-0]很好奇。它必须匹配-0中的一个,因此像123这样的数字不会匹配,除非它前面有一个0,例如0123... - SF Lee
@SFLee 是的,这就是为什么我使用了 String.format("%05d", number) - Braj
@SFLee,我已经修改了我的帖子。现在它对于2046也可以正常工作了。再次感谢您的测试。 - Braj
OP正在使用OCaml语言,该语言没有string.format函数。因此,最好提供一个使用纯正则表达式的解决方案。 - SF Lee

0

试试这个:

^-?0*(1?[0-9]{1,3}|20[0-4][0-9]|205[0-5])$

方括号前的正则表达式匹配可选的-和任何前导0。

括号中的第一部分(1?[0-9]{1,3})匹配0-1999。

括号中的第二部分(20 [0-4] [0-9])匹配2000-2049。

括号中的第三部分(205 [0-5])匹配2050-2055。


很好的回答,但你抢走了我的想法。 :) - Braj
@Braj 哈哈...我在查看其他答案(包括你的)之前就发布了这个答案。查看时间戳以获取证明。 - SF Lee
为什么需要无限前导零? - mickmackusa
为什么不行呢?它们是有效的数字。 - SF Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接