Skip to content Skip to sidebar Skip to footer

Convert Human Readable Number Range To Regex

I have a table that is displayed using datatables, above each column I have an empty text form field that users can type in terms to filter on. This works fine on all text fields,

Solution 1:

Validating a number is in a range of numbers with regex is tricky problem. These regexs will match a number within a given range:

\b[0-9]{1,7}\b        #   0-9999999
\b[1-9][0-9]{2,6}\b   # 100-9999999
\b([4-9][0-9]{4}|[1-9][0-9]{5,6})\b   # 40000-9999999

It starts to get out of hand when you have complex ranges

\b(?:5(?:4(?:3(?:2[1-9]|[3-9][0-9])|[4-9][0-9]{2})|[5-9][0-9]{3})|[6-9][0-9]{4}|[1-9][0-9]{5}|[1-8][0-9]{6}|9(?:[0-7][0-9]{5}|8(?:[0-6][0-9]{4}|7(?:[0-5][0-9]{3}|6(?:[0-4][0-9]{2}|5(?:[0-3][0-9]|4[0-3]))))))\b # 54321-9876543

enter image description here

Solution 2:

Forward

3 years later I rediscovered this question, and had some time to solve the puzzle. I'm not entirely clear on why you'd want to use a regex, but I'm sure it has to do with improving database return performance by not forcing all possible results to the client where they'll be evaluated.

That said, I'm sure you have your reasons.

Explanation

This set of functions will construct a regular expression that will do the following:

  • validate a given number is between a given range of positive integer numbers
  • rejects numbers that are outside that range
  • requires the entire string to be numbers
  • works with any size numbers
  • allow the entire range to include the lower and upper numbers

General overview

The function funRegexRange does all the heavy lifting. By building a string that will match all numbers from 0 to UpperRange

The function funBuildRegexForRange then constructs the actual regex with a negative lookahead and a positive lookahead.

The resulting regex will then validate your number is between 0 and the UpperRange inclusive, and not between 0 and the LowerRange not inclusive.

The functions will allow either numbers or strings values, but does not validate the inputs are integers. Providing values which do not equate to integers will yield unpredictable results.

Examples

To get the regex for a range from 400 to 500:

re = funBuildRegexForRange( 400, 500, true ) 

By setting the last parameter to true you it'll show the various parts being constructed and the full regex.

[0-3][0-9]{2}, [0-9]{1,2}
[0-4][0-9]{2}, 500, [0-9]{1,2}
Full Regex = /^(?!(?:[0-3][0-9]{2}|[0-9]{1,2})$)(?=(?:[0-4][0-9]{2}|500|[0-9]{1,2})$)/

The resulting regex looks like

Regular expression visualization

Asking for a range between 400 - 999999999999 [twelve digits] returns this monster:

Full Regex = /^(?!(?:[0-3][0-9]{2}|[0-9]{1,2})$)(?=(?:[0-8][0-9]{11}|9[0-8][0-9]{10}|99[0-8][0-9]{9}|999[0-8][0-9]{8}|9999[0-8][0-9]{7}|99999[0-8][0-9]{6}|999999[0-8][0-9]{5}|9999999[0-8][0-9]{4}|99999999[0-8][0-9]{3}|999999999[0-8][0-9]{2}|9999999999[0-8][0-9]|99999999999[0-8]|999999999999|[0-9]{1,11})$)/

Javascript Code

Live Example: https://repl.it/CLd4/4

Full code:

functionfunRegexRange (UpperRange, Inclusive, Debug) {
    // this function will build a basic regex that will match a range of integers from 0 to UpperRangeUpperRange += ""// convert the value to a stringvarArrUpperRange = UpperRange.split("")
    var intLength = ArrUpperRange.lengthvarLastNumber = ArrUpperRange[intLength]
    varAllSubParts = []
    varSubPortion = ""for (i = 0; i < intLength; i++) {
        Position = intLength - (i +1)
        if ( Position >= 2 ) { 
            Trailing = "[0-9]{" + Position + "}";
        } elseif ( Position == 1 ) {
            Trailing = "[0-9]";
        } else {
            Trailing = "";
        }
        
        if ( ArrUpperRange[i] >= 2 ) {
            ThisRange = "[0-" + (ArrUpperRange[i] - 1) + "]"
        } elseif ( ArrUpperRange[i] == 1 ) {
            ThisRange = "0"
        } else {
            ThisRange = ""
        }
    
        if ( Debug ) {  
        // console.log( "Pos='" + Position + "' i='" + i + "' char='" + ArrUpperRange[i] + "' ThisRange='" + ThisRange + "' Trailing='" + Trailing + "'")
        }
    
        if ( ThisRange === "" && Trailing !== "" ) {
            // no need to return the this as this will be matched by the future SubPortions
        } else {
            if ( Position === 0 && ThisRange ==="" && Trailing === "") {
            } else {
                AllSubParts.push( SubPortion + ThisRange + Trailing);
        }
        }
    SubPortion += ArrUpperRange[i]
    }
    
    // insert the last number if this it should be included in the rangeif ( Inclusive ) {
        AllSubParts.push(UpperRange)
    }
    
    // all all numbers that have less digits than the rangeif ( intLength - 1 >= 2 ) { 
        Trailing = "[0-9]{1," + ( intLength - 1 ) + "}";
    } elseif ( intLength - 1 >= 1 ) {
        Trailing = "[0-9]";
    } else {
        Trailing = "";
    }
    
    // insert trailing into the output streamif ( Trailing ){
        AllSubParts.push( Trailing );
    }   
    
    if ( Debug ) {
        console.log(AllSubParts.join(", "));
    } 
    returnAllSubParts.join("|");
} // end function funRegexRangefunctionfunBuildRegexForRange ( Start, End, Debug ){
    varRegex = newRegExp("^(?!(?:" + funRegexRange (LowerRange, false, Debug) + ")$)(?=(?:" + funRegexRange (UpperRange, true, Debug) + ")$)" ,"" )   
    if ( Debug ) {
        console.log("Full Regex = " + Regex + "")
    }
    returnRegex
}

varDebug = false;
varInclusive = true;
varLowerRange = "400";
varUpperRange = "500";

// var re = funBuildRegexForRange( LowerRange, UpperRange, true ) if ( Debug ){
    for (Range = 0; Range < 13; Range++) {
        console.log ("funRegexRange ('" + Range + "', " + Inclusive +") =");
        funRegexRange (Range, Inclusive, Debug);
        console.log ("");
    }
}

varRegex = funBuildRegexForRange( LowerRange, UpperRange, Debug ) 

for (i = 1000; i < 1020; i++) {
    TestNumber = i + ""if ( TestNumber.match(Regex)) {
        console.log(TestNumber + " TestNumber='" + TestNumber + "' matches");
    } else {
//      console.log(TestNumber + " does not match '" + Regex + "'")
    }
}

Post a Comment for "Convert Human Readable Number Range To Regex"