在设计正则表达式的时候,我们通常需要在表达式的准确性和复杂性之间做出权衡,ip地址的匹配就是一个很好的例子。
例如\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
足够匹配出所有的ip地址,但是它也可以匹配非法的地址,例如 999.999.999.999。如果你使用的正则引擎支持Unicode,那么这个表达式也匹配١٢٣.१२३.೧೨೩.๑๒๓。我们需要根据数据源以及使用场景来权衡表达式的准确性和复杂性。
下面的正则表达式可以把数字限定为0到255之间的数字,它把四个数字放入到四个匹配组中。你可以使用这些匹配组进一步处理ip地址。
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\. (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\. (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\. (25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
在上面这个表达式中每个匹配组中的内容都相同,即(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
。这个表达式可以匹配以0为前缀的数字,例如01,001,000。严格来说以0为前缀的地址表示八进制数字,所以你可能需要禁用这种地址。你可以使用以下表达式提升表达式的准确性:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])
。
到此为止我们一共提出了三种匹配方案,其中第二种和第三种使用了匹配组。使用匹配组的目的是为了进一步处理ip中的数字,但是匹配组不是必须的,我们可以使用量词来简化这个三个表达式。
\b(?:\d{1,3}\.){3}\d{1,3}\b
\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3} (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3} (?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b
上文中所使用的表达式使用了词语边界\b
,这是为了确保匹配结果不属于更长的字符串的一部分,所以这些表达式适合用户搜索文本中的ip地址。
如果你想校验用户的输入,并且确保输入包含且仅包含合法的ip地址,那么你需要把词语边界替换成字符串开始位置和结束位置。例如:^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3} (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
。
如果文章出现错误,请给我提Issues - - Github地址
需要进一步翻译的内容:
- backreferences
- lookaround