Javascript多个正则表达式模式

时间:2012-04-19 20:44:42

标签: javascript regex

我试图排除一些内部IP地址和一些内部IP地址格式,以查看站点中的某些徽标和链接。我有多种IP地址范围(下面给出的示例)。是否可以使用javascript编写一个可以匹配下面列表中所有IP地址的正则表达式?

10.X.X.X
12.122.X.X
12.211.X.X
64.X.X.X
64.23.X.X
74.23.211.92
and 10 more

5 个答案:

答案 0 :(得分:3)

引用句点,用\d+替换X,然后将它们与管道连接起来:

var allowedIPpatterns = [ 
  "10.X.X.X", 
  "12.122.X.X",
  "12.211.X.X",
  "64.X.X.X",
  "64.23.X.X",
  "74.23.211.92"   //, etc.
];

var allowedRegexStr = '^(?:' + 
  allowedIPpatterns.
    join('|').
    replace(/\./g, '\\.').
    replace(/X/g, '\d+') + 
  ')$';

 var allowedRegexp = new RegExp(allowedRegexStr);

然后你就完成了:

 '10.1.2.3'.match(allowedRegexp) // => ['10.1.2.3']
 '100.1.2.3'.match(allowedRegexp) // => null

如果您的输入可能根本不是合法的IP地址,则可以将'\d+'更改为仅与有效字节值匹配的内容,例如'(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])'

工作原理:

首先,我们必须将各个IP模式转换为与其意图相匹配的正则表达式。 “形式为'12 .122.X.X'的所有IP”的一个正则表达式为:

^12\.122\.\d+\.\d+$

  • ^表示匹配必须从字符串的开头开始;否则,112.122.X.X IP也会匹配。
  • 12等:数字匹配自己
  • \.:正则表达式中的句点与任何字符匹配;我们想要文字句号,所以我们在前面加上反斜杠。
  • \d[0-9]的简写;匹配任何数字。
  • +:表示“1或更多” - 在这种情况下为1位或更多位数。
  • $:与^类似,这意味着匹配必须在字符串末尾结束。

因此,我们将IP模式转变为这样的正则表达式。对于单个模式,您可以使用以下代码:

var regexStr = `^` + ipXpattern. 
  replace(/\./g, '\\.').
  replace(/X/g, '\\d+') + 
  `$`;

只需将所有.替换为\.,将X替换为\d+,并将^$放在最后。

在正则表达式中,替换 this|that匹配与thisthat匹配的任何内容。因此,如果我们将列表转换为re1|re2|re3|...|relast形式的单个正则表达式,我们可以立即检查所有IP的匹配。

然后我们可以做一些重构,使正则表达式匹配器的工作更容易;在这种情况下,由于所有正则表达式都将具有^...$,我们可以将这些约束移出单个正则表达式并将它们放在整个事物上:^(10\.\d+\.\d+\.\d+|12\.122\.\d+\.\d+|...)$。括号使^不仅仅是第一个模式的一部分而$只是最后一个模式的一部分。但由于普通括号既可以捕获也可以捕获组,我们不需要捕获任何内容,我将其替换为非分组版本(?: .. )

在这种情况下,我们可以在巨型字符串上进行一次全局搜索和替换,而不是在每个模式上单独进行。结果就是上面的代码:

var allowedRegexStr = '^(?:' + 
  allowedIPpatterns.
    join('|').
    replace(/\./g, '\\.').
    replace(/X/g, '\d+') + 
  ')$';

那仍然只是一个字符串;我们必须将它变成一个实际的RegExp对象来进行匹配:

var allowedRegexp = new RegExp(allowedRegexStr);

如上所述,这不会过滤掉非法IP - 例如,10.1234.5678.9012将匹配第一个模式。如果要将单个字节值限制为小数范围0-255,则可以使用比\d+更复杂的正则表达式,如下所示:

(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])

这意味着“任何一个或两个数字,或'1'后跟任意两个数字,或'2'后跟任何'0'到'4'后跟任何数字,或'25'后跟任何数字'0'到'5'“。

这使整个正则表达式字符串看起来更加笨拙:

^(?:10\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])\.(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]).(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])|12\.122\....

但你不必看它,只是匹配它。 :)

答案 1 :(得分:1)

你可以在正则表达式中做到这一点,但它不会很漂亮,特别是因为JavaScript甚至不支持冗长的正则表达式,这意味着它必须是一个庞大的正则表达式而没有任何注释。此外,正则表达式不适合匹配数字范围。我怀疑有更好的工具可以解决这个问题。

好的,好的,这里(对于你提供的样品):

var myregexp = /\b(?:74\.23\.211\.92|(?:12\.(?:122|211)|64\.23)\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])|(?:10|64)\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]))\b/g;

作为详细(“可读”)正则表达式:

\b                 # start of number
(?:                # Either match...
 74\.23\.211\.92   # an explicit address
|                  # or
 (?:               # an address that starts with
  12\.(?:122|211)  # 12.122 or 12.211
 |                 # or
  64\.23           # 64.23
 )
 \.                # . 
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.  # followed by 0..255 and a dot
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])    # followed by 0..255
|                  # or
 (?:10|64)         # match 10 or 64
 \.                # . 
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.  # followed by 0..255 and a dot
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.  # followed by 0..255 and a dot
 (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])    # followed by 0..255
)
\b                 # end of number

答案 2 :(得分:0)

/^(X|\d{1,3})(\.(X|\d{1,3})){3}$/应该这样做。

答案 3 :(得分:0)

如果你实际上不需要匹配“X”字符,你可以使用它:

\b(?:\d{1,3}\.){3}\d{1,3}\b

否则我会使用cebarrett提供的解决方案。

答案 4 :(得分:0)

我不完全确定你在这里想要达到的目标(看起来不是其他任何人)。

但是,如果它是验证,那么这是一个验证不使用RegEx的IP地址的解决方案。首先,将输入字符串拆分为点。然后在数字上使用parseInt,确保它不高于255。

function ipValidator(ipAddress) {
var ipSegments = ipAddress.split('.');
for(var i=0;i<ipSegments.length;i++)
    {
        if(parseInt(ipSegments[i]) > 255){
            return 'fail';
        }
    }
return 'match';
}

运行以下命令会返回'匹配':

document.write(ipValidator('10.255.255.125'));

然而这将返回'失败':

document.write(ipValidator('10.255.256.125'));

以下是jsfiddle中的一个着名版本,其中包含一些示例http://jsfiddle.net/VGp2p/2/