2011-10-25 44 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