2011-10-25 45 views
1

我正在尋找一種方法來構造正則表達式來匹配由給定整數範圍指定的數字輸入,即。如果我通過在一個範圍內1,3-4然後一個正則表達式將返回匹配的只有1,3和4構造正則表達式以匹配數字範圍

我寫了下面的方法,試圖做到這一點:

function generateRegex(values) { 
    if (values == "*") { 
     return new RegExp("^[0-9]+$"); 
    } else { 
     return new RegExp("^[" + values + "]+$"); 
    } 
} 

我有時我需要匹配兩位數字,例如"8-16",而且我還需要確保如果傳遞了一個數字值(如"1"),則生成的正則表達式僅匹配1,而不是匹配11

我真的希望這是一個非常小的代碼片段,但我不太確定正則表達式知道如何做到這一點。將非常感謝任何幫助!

編輯:我意識到我不清楚,我的原始段落,所以編輯它。我意識到我最初生成的正則表達式根本不起作用

+0

'/^[0,3-4] + $ /''的'0',''混合匹配3'和'4''像000,,, 34,000'。絕對不是你想要的。 – lkuty

+0

'0,3-4' =>'/^[0,3-4] + $ /'是錯誤的。它將匹配33,44。正確的表達方式將會是'/ ^''/' – xanatos

+0

做你想做的事情是可行的......但是它非常複雜。我會說半天/一天的工作。第一個提示是你必須用'|'替換''',基本表達式應該是'^(piece1 | piece2)$' – xanatos

回答

0

我不確定是否有一種(理智的)方法來使用RegExp測試整數範圍。我相信你會注意RegExp,那裏有更簡單(更靈活)的方法。看看IntRangeTest()

var range = new IntRangeTest('0,10-20'); 
console.log(
    "0,10-20", 
    range.test("") == false, 
    range.test("-5") == false, 
    range.test("0") == true, 
    range.test("5") == false, 
    range.test("11") == true, 
    range.test("123.23") == false 
); 

如果您覺得喜歡它,您可以輕鬆地將其添加到Number.prototype。如果這是您所擔心的,那麼您也可以很容易地將其作爲RegExp的擴展。

+0

唉,我剛剛得到它與正則表達式的工作!這是一個更好的解決方案,但不能相信我浪費了多少時間! –

+2

有句諺語......»有些人遇到問題時,會想:「我知道,我會用正則表達式。」現在他們有兩個問題。«RegExp岩石 - 但肯定不是所有東西:) – rodneyrehm

1

正則表達式不知道關於數字的任何內容,只有數字。所以[8-16]是無效的,因爲你說8和1之間的匹配(而不是1和8例如)加上數字6. 如果你想匹配數字,你必須考慮它們的詞法。例如,以1到30之間匹配的數字,你必須寫類似(其他的正則表達式存在):

/^(30|[1-2]\d|[1-9])$/ 
0

好了,所以它似乎有4個主要的情況是,我需要解決:

  • 個位數,即1,只會產生正則表達式/^1$/
  • 多位數,即12,將需要正則表達式/^12&/
  • 一位數的範圍,即3-6,會生成正則表達式/^[3-6]$/
  • 最後,多個數字範圍以類似的方法工作到多個數字但是有一個範圍,即11-14將變成/^1[1-4]$/。這些都需要,如果他們跨越多重啓動數字拆分成多個正則表達式,即23-31將成爲/^2[3-9]|3[0-1]$/

因此,所有我需要做的是找出每種情況下,並使用|像薩那託斯的化合物,正則表達式建議。即,以匹配所有的上述標準會產生這樣一個正則表達式:

/^(1 | 12 | [3-6] | 1[1-4] | 2[3-9]|3[0-1])$/ 

做其他的同意,這似乎是取得進展的體面的方式?

1

我確定它是4-8小時:-)最後(以及它的無用),這是編寫正則表達式的一個很好的練習。你可以自由嘗試。如果我們排除continue的使用和Array構造函數的使用,則完全可以使用jsLint。

var BuildRegex = function(matches) { 
    "use strict"; 

    var splits = matches.split(','), 
     res = '^(', 
     i, subSplit, min, max, temp, tempMin; 

    if (splits.length === 0) { 
     return new RegExp('^()$'); 
    } 

    for (i = 0; i < splits.length; i += 1) { 
     if (splits[i] === '*') { 
      return new RegExp('^([0-9]+)$'); 
     } 

     subSplit = splits[i].split('-'); 

     min = BuildRegex.Trim(subSplit[0], '0'); 

     if (min === '') { 
      return null; 
     } 

     if (subSplit.length === 1) { 
      res += min; 
      res += '|'; 

      continue; 
     } else if (subSplit.length > 2) { 
      return null; 
     } 

     max = BuildRegex.Trim(subSplit[1], '0'); 

     if (max === '') { 
      return null; 
     } 

     if (min.length > max.length) { 
      return null; 
     } 

     // For 2-998 we first produce 2-9, then 10-99 
     temp = BuildRegex.DifferentLength(res, min, max); 

     tempMin = temp.min; 

     if (tempMin === null) { 
      return null; 
     } 

     res = temp.res; 

     // Then here 100-998 
     res = BuildRegex.SameLength(res, tempMin, max); 
    } 

    res = res.substr(0, res.length - 1); 
    res += ')$'; 

    return new RegExp(res); 
}; 

BuildRegex.Repeat = function(ch, n) { 
    "use strict"; 

    return new Array(n + 1).join(ch); 
}; 

BuildRegex.Trim = function(str, ch) { 
    "use strict"; 

    var i = 0; 

    while (i < str.length && str[i] === ch) { 
     i += 1; 
    } 

    return str.substr(i); 
}; 

BuildRegex.IsOnlyDigit = function(str, start, digit) { 
    "use strict"; 

    var i; 

    for (i = start; i < str.length; i += 1) { 
     if (str[i] !== digit) { 
      return false; 
     } 
    } 

    return true; 
}; 

BuildRegex.RangeDigit = function(min, max) { 
    "use strict"; 

    if (min === max) { 
     return min; 
    } 

    return '[' + min + '-' + max + ']'; 
}; 

BuildRegex.DifferentLength = function(res, min, max) { 
    "use strict"; 

    var tempMin = min, 
     i, tempMax; 

    for (i = min.length; i < max.length; i += 1) { 
     tempMax = BuildRegex.Repeat('9', i); 

     res = BuildRegex.SameLength(res, tempMin, tempMax); 

     tempMin = '1' + BuildRegex.Repeat('0', i); 
    } 

    if (tempMin > tempMax) { 
     return null; 
    } 

    return { 
     min: tempMin, 
     res: res 
    }; 
}; 

BuildRegex.SameLength = function(res, min, max) { 
    "use strict"; 

    var commonPart; 

    // 100-100 
    if (min === max) { 
     res += min; 
     res += '|'; 

     return res; 
    } 

    for (commonPart = 0; commonPart < min.length; commonPart += 1) { 
     if (min[commonPart] !== max[commonPart]) { 
      break; 
     } 
    } 

    res = BuildRegex.RecursivelyAddRange(res, min.substr(0, commonPart), min.substr(commonPart), max.substr(commonPart)); 

    return res; 
}; 

BuildRegex.RecursivelyAddRange = function(res, prefix, min, max) { 
    "use strict"; 

    var only0Min, only9Max, i, middleMin, middleMax; 

    if (min.length === 1) { 
     res += prefix; 
     res += BuildRegex.RangeDigit(min[0], max[0]); 
     res += '|'; 

     return res; 
    } 

    // Check if 
    only0Min = BuildRegex.IsOnlyDigit(min, 1, '0'); 
    only9Max = BuildRegex.IsOnlyDigit(max, 1, '9'); 

    if (only0Min && only9Max) { 
     res += prefix; 
     res += BuildRegex.RangeDigit(min[0], max[0]); 

     for (i = 1; i < min.length; i += 1) { 
      res += '[0-9]'; 
     } 

     res += '|'; 

     return res; 
    } 

    middleMin = min; 

    if (!only0Min) { 
     res = BuildRegex.RecursivelyAddRange(res, prefix + min[0], min.substr(1), BuildRegex.Repeat('9', min.length - 1)); 

     if (min[0] !== '9') { 
      middleMin = String.fromCharCode(min.charCodeAt(0) + 1) + BuildRegex.Repeat('0', min.length - 1); 
     } else { 
      middleMin = null; 
     } 
    } 

    middleMax = max; 

    if (!only9Max) { 
     if (max[0] !== '0') { 
      middleMax = String.fromCharCode(max.charCodeAt(0) - 1) + BuildRegex.Repeat('9', max.length - 1); 
     } else { 
      middleMax = null; 
     } 
    } 

    if (middleMin !== null && middleMax !== null && middleMin[0] <= middleMax[0]) { 
     res = BuildRegex.RecursivelyAddRange(res, prefix + BuildRegex.RangeDigit(middleMin[0], middleMax[0]), middleMin.substr(1), middleMax.substr(1)); 
    } 

    if (!only9Max) { 
     res = BuildRegex.RecursivelyAddRange(res, prefix + max[0], BuildRegex.Repeat('0', max.length - 1), max.substr(1)); 
    } 

    return res; 
}; 

// ---------------------------------------------------------- 

var printRegex = function(p) { 
    "use strict"; 

    document.write(p + ': ' + BuildRegex(p) + '<br>'); 
}; 

printRegex('*'); 
printRegex('1'); 
printRegex('1,*'); 
printRegex('1,2,3,4'); 
printRegex('1,11-88'); 
printRegex('1,11-88,90-101'); 
printRegex('1-11111'); 
printRegex('75-11119'); 

這裏測試http://jsfiddle.net/dnqYV/

C#的版本在這裏http://ideone.com/3aEt3E