{"id":2344,"date":"2015-11-05T11:35:21","date_gmt":"2015-11-05T11:35:21","guid":{"rendered":"http:\/\/blog.designed79.co.uk\/?p=2344"},"modified":"2015-11-05T11:35:21","modified_gmt":"2015-11-05T11:35:21","slug":"matching-numeric-ranges-with-a-regular-expression","status":"publish","type":"post","link":"https:\/\/blog.designed79.co.uk\/?p=2344","title":{"rendered":"Matching Numeric Ranges with a Regular Expression"},"content":{"rendered":"<p>Since\u00a0<a href=\"http:\/\/www.regular-expressions.info\/tutorial.html\" target=\"_top\">regular expressions<\/a>\u00a0deal with text rather than with numbers, matching a number in a given range takes a little extra care. You can&#8217;t just write\u00a0<tt class=\"regex\">[0-255]<\/tt>\u00a0to match a number between 0 and 255. Though a valid regex, it matches something entirely different.\u00a0<tt class=\"regex\">[0-255]<\/tt>\u00a0is a\u00a0<a href=\"http:\/\/www.regular-expressions.info\/charclass.html\" target=\"_top\">character class<\/a>\u00a0with three elements: the character range 0-2, the character 5 and the character 5 (again). This character class matches a single digit 0, 1, 2 or 5, just like\u00a0<tt class=\"regex\">[0125]<\/tt>.<\/p>\n<p>Since regular expressions work with text, a regular expression engine treats\u00a0<tt class=\"string\">0<\/tt>\u00a0as a single character, and\u00a0<tt class=\"string\">255<\/tt>\u00a0as three characters. To match all characters from 0 to 255, we&#8217;ll need a regex that matches between one and three characters.<\/p>\n<p>The regex\u00a0<tt class=\"regex\">[0-9]<\/tt>\u00a0matches single-digit numbers 0 to 9.\u00a0<tt class=\"regex\">[1-9][0-9]<\/tt>\u00a0matches double-digit numbers 10 to 99. That&#8217;s the easy part.<\/p>\n<p>Matching the three-digit numbers is a little more complicated, since we need to exclude numbers 256 through 999.\u00a0<tt class=\"regex\">1[0-9][0-9]<\/tt>\u00a0takes care of 100 to 199.\u00a0<tt class=\"regex\">2[0-4][0-9]<\/tt>\u00a0matches 200 through 249. Finally,\u00a0<tt class=\"regex\">25[0-5]<\/tt>\u00a0adds 250 till 255.<\/p>\n<p>As you can see, you need to split up the numeric range in ranges with the same number of digits, and each of those ranges that allow the same variation for each digit. In the 3-digit range in our example, numbers starting with 1 allow all 10 digits for the following two digits, while numbers starting with 2 restrict the digits that are allowed to follow.<\/p>\n<p>Putting this all together using\u00a0<a href=\"http:\/\/www.regular-expressions.info\/alternation.html\" target=\"_top\">alternation<\/a>\u00a0we get:\u00a0<tt class=\"regex\">[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]<\/tt>. This matches the numbers we want, with one caveat: regular expression searches usually allow partial matches, so our regex would match\u00a0<tt class=\"match\">123<\/tt>\u00a0in\u00a0<tt class=\"string\">12345<\/tt>. There are two solutions to this.<\/p>\n<p>If you&#8217;re searching for these numbers in a larger document or input string, use\u00a0<a href=\"http:\/\/www.regular-expressions.info\/wordboundaries.html\" target=\"_top\">word boundaries<\/a>\u00a0to require a non-word character (or no character at all) to precede and to follow any valid match. The regex then becomes\u00a0<tt class=\"regex\">\\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\b<\/tt>. Since the alternation operator has the lowest precedence of all, the\u00a0<a href=\"http:\/\/www.regular-expressions.info\/brackets.html\" target=\"_top\">parentheses<\/a>\u00a0are required to group the alternatives together. This way the regex engine will try to match the first word boundary, then try all the alternatives, and then try to match the second word boundary after the numbers it matched. Regular expression engines consider all alphanumeric characters, as well as the underscore, as word characters.<\/p>\n<p>If you&#8217;re using the regular expression to validate input, you&#8217;ll probably want to check that the entire input consists of a valid number. To do this, replace the word boundaries with\u00a0<a href=\"http:\/\/www.regular-expressions.info\/anchors.html\" target=\"_top\">anchors<\/a>\u00a0to match the start and end of the string:\u00a0<tt class=\"regex\">^([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$<\/tt>.<\/p>\n<p>Here are a few more common ranges that you may want to match:<\/p>\n<ul>\n<li>000..255:\u00a0<tt class=\"regex\">^([01][0-9][0-9]|2[0-4][0-9]|25[0-5])$<\/tt><\/li>\n<li>0 or 000..255:\u00a0<tt class=\"regex\">^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$<\/tt><\/li>\n<li>0 or 000..127:\u00a0<tt class=\"regex\">^(0?[0-9]?[0-9]|1[01][0-9]|12[0-7])$<\/tt><\/li>\n<li>0..999:\u00a0<tt class=\"regex\">^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$<\/tt><\/li>\n<li>000..999:\u00a0<tt class=\"regex\">^[0-9]{3}$<\/tt><\/li>\n<li>0 or 000..999:\u00a0<tt class=\"regex\">^[0-9]{1,3}$<\/tt><\/li>\n<li>1..999:\u00a0<tt class=\"regex\">^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$<\/tt><\/li>\n<li>001..999:\u00a0<tt class=\"regex\">^(00[1-9]|0[1-9][0-9]|[1-9][0-9][0-9])$<\/tt><\/li>\n<li>1 or 001..999:\u00a0<tt class=\"regex\">^(0{0,2}[1-9]|0?[1-9][0-9]|[1-9][0-9][0-9])$<\/tt><\/li>\n<li>0 or 00..59:\u00a0<tt class=\"regex\">^[0-5]?[0-9]$<\/tt><\/li>\n<li>0 or 000..366:\u00a0<tt class=\"regex\">^(0?[0-9]?[0-9]|[1-2][0-9][0-9]|3[0-5][0-9]|36[0-6])$<\/tt><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Since\u00a0regular expressions\u00a0deal with text rather than with numbers, matching a number in a given range takes a little extra care. You can&#8217;t [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2344","post","type-post","status-publish","format-standard","hentry","category-info-on-tech"],"_links":{"self":[{"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2344","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2344"}],"version-history":[{"count":0,"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/2344\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.designed79.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}