簡體   English   中英

將人類可讀的數字范圍轉換為正則表達式

[英]Convert human readable number range to Regex

我有一個使用數據表顯示的表,在每一列的上方都有一個空的文本表單字段,用戶可以根據其輸入內容進行過濾。 這在所有文本字段上都可以正常工作,在整數字段上也可以。 我正在對某些術語進行某種轉換,例如,如果用戶鍵入NULL或NOT NULL,則將其轉換為regex ^ $或。

我知道正則表達式旨在搜索文本字符串,但這就是數據表所使用的,因此這就是我這樣做的原因。 我想要的是用戶能夠輸入“ x to y”之類的值並將其轉換為正則表達式。 我找不到執行此操作的函數,如果有人知道一個函數,請告訴我。

假設尚不存在函數,則假設僅搜索正整數,並說最多7位數字。 因此可以搜索0-9,999,999。 同樣,觸發此方法的唯一方法是使用關鍵字to,使其帶有空格“至”。

所以這樣的事情開始:

function convertNumRangeRegex(s){

if(s.indexOf(" to ") != -1){
var range = s.split(" to ");
lowRange = Number(range[0]);
highRange = Number(range[1]);   

if(lowRange >= 0 && lowRange < 10 && highRange < 10){
        s = "^[" + lowRange + "-" + highRange + "]$";
}};


return s; 
};

這適用於數字0-9,但對此進行擴展似乎很難看。 我支持任何想法。 謝謝。

使用正則表達式驗證數字是否在數字范圍內是一個棘手的問題。 這些正則表達式將匹配給定范圍內的數字:

\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

當您有復雜的范圍時,它開始失控

\\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

在此處輸入圖片說明

向前

3年后,我重新發現了這個問題,並花了一些時間解決這個難題。 對於您為什么要使用正則表達式,我尚不完全清楚,但是我敢肯定,這與通過不將所有可能的結果強制提供給客戶端進行評估來提高數據庫的返回性能有關。

就是說,我確定您有您的理由。

說明

這組函數將構造一個執行以下操作的正則表達式:

  • 驗證給定數字在給定范圍內的正整數之間
  • 拒絕超出該范圍的數字
  • 要求整個字符串為數字
  • 適用於任何大小的數字
  • 允許整個范圍包括上限和下限

總體概述

函數funRegexRange完成所有繁重的工作。 通過構建將匹配從0UpperRange所有數字的字符串

然后,函數funBuildRegexForRange構造具有負先行和正先行的實際正則表達式。

然后,生成的正則表達式將驗證您的數字是否介於0UpperRange之間(包括UpperRange ,而不是介於0LowerRange之間(不包括LowerRange

該函數將允許數字或字符串值,但不驗證輸入是否為整數。 提供不等於整數的值將產生不可預測的結果。

例子

要獲取介於400到500之間的正則表達式:

re = funBuildRegexForRange( 400, 500, true ) 

通過將最后一個參數設置為true,將顯示正在構造的各個部分以及完整的正則表達式。

[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})$)/

生成的正則表達式看起來像

正則表達式可視化

要求范圍在400-999999999999 [十二個數字]之間,則會返回此怪物:

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代碼

實時示例: https//repl.it/CLd4/4

完整代碼:

function funRegexRange (UpperRange, Inclusive, Debug) {
    // this function will build a basic regex that will match a range of integers from 0 to UpperRange

    UpperRange += "" // convert the value to a string
    var ArrUpperRange = UpperRange.split("")
    var intLength = ArrUpperRange.length
    var LastNumber = ArrUpperRange[intLength]
    var AllSubParts = []
    var SubPortion = ""

    for (i = 0; i < intLength; i++) {
        Position = intLength - (i +1)
        if ( Position >= 2 ) { 
            Trailing = "[0-9]{" + Position + "}";
        } else if ( Position == 1 ) {
            Trailing = "[0-9]";
        } else {
            Trailing = "";
        }

        if ( ArrUpperRange[i] >= 2 ) {
            ThisRange = "[0-" + (ArrUpperRange[i] - 1) + "]"
        } else if ( 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 range
    if ( Inclusive ) {
        AllSubParts.push(UpperRange)
    }

    // all all numbers that have less digits than the range
    if ( intLength - 1 >= 2 ) { 
        Trailing = "[0-9]{1," + ( intLength - 1 ) + "}";
    } else if ( intLength - 1 >= 1 ) {
        Trailing = "[0-9]";
    } else {
        Trailing = "";
    }

    // insert trailing into the output stream
    if ( Trailing ){
        AllSubParts.push( Trailing );
    }   

    if ( Debug ) {
        console.log(AllSubParts.join(", "));
    } 
    return AllSubParts.join("|");
} // end function funRegexRange


function funBuildRegexForRange ( Start, End, Debug ){
    var Regex = new RegExp("^(?!(?:" + funRegexRange (LowerRange, false, Debug) + ")$)(?=(?:" + funRegexRange (UpperRange, true, Debug) + ")$)" ,"" )   
    if ( Debug ) {
        console.log("Full Regex = " + Regex + "")
    }
    return Regex
}

var Debug = false;
var Inclusive = true;
var LowerRange = "400";
var UpperRange = "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 ("");
    }
}

var Regex = 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 + "'")
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM