我试图排除一些内部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
答案 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
匹配与this
或that
匹配的任何内容。因此,如果我们将列表转换为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/