【问题标题】:java regular expression IP address pattern matchjava正则表达式IP地址模式匹配
【发布时间】:2012-05-17 09:19:04
【问题描述】:

为了区分内部用户和外部用户,我在scriplet标签中使用了java正则表达式,代码如下:

String ipAddress  = request.getHeader("iv-remote-address");

String internalIPs = 
"166.41.8.X" + "|" +"12.16.X.X" + "|" +"12.22.X.X" + "|" +"132.23.X.X" + "|";

Pattern p = Pattern.compile("^(?:"+internalIPs.replaceAll("X", "(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])")+")$");

Matcher m = p.matcher(ipAddress);

if (m.matches())
{
    //print internal IP     
} else{
    //print external IP 
}   

如果输入的是166.41.8.2,则IP地址被正确识别为内部IP 如果输入为 12.16.2.1 或 12.22.12.3,则 IP 地址未正确识别为内部 IP。我想这与匹配模式与 2 个“X”有关。任何人都可以识别模式匹配的问题吗?或者可以推荐一种匹配 IP 地址模式的最佳方法?

【问题讨论】:

标签: java jsp


【解决方案1】:

2 处更正:

  1. 句号 . 应该转义,否则表示任何字符
  2. \\d 在您的 replaceAll 调用中需要双重转义,因为这最终成为您的最终正则表达式。

这是工作代码:

String ipAddress  = "12.16.2.1";
String internalIPs = 
"166\\.41\\.8\\.X" + "|" +"12\\.16\\.X\\.X" + "|" +
"12\\.22\\.X\\.X" + "|" +"132\\.23\\.X\\.X" + "|";

Pattern p = Pattern.compile("^(?:"+internalIPs.replaceAll("X",
                            "(?:\\\\d{1,2}|1\\\\d{2}|2[0-4]\\\\d|25[0-5])")+")$");

//System.out.println(p.pattern());

Matcher m = p.matcher(ipAddress);
if (m.matches())
    System.out.println("print internal IP"); // gets printed  
else
    System.out.println("print external IP"); 

备选方案:

由于您在internalIPs.replaceAll 调用中并没有真正使用任何正则表达式,因此最好使用String#replace 方法(它不支持正则表达式),这样就不需要双重转义。所以就这样使用吧:

Pattern p = Pattern.compile("^(?:" + internalIPs.replace("X",
                            "(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])")+")$");

【讨论】:

  • @JamesMontagne:在 OP 正在构建的最终正则表达式中,它在 OP 代码 \\d{1,2} 中的方式最终将变为 d{1,2}。这就是为什么它需要双重转义。
  • 是的,我只是觉得有点不清楚,为什么斜线会完全消失。但我删除了我的评论,因为在写完之后,我不确定它是否更清楚(或完全正确)。
  • @JamesMontagne:另请参阅我的替代选项。由于 OP 在 replaceAll 调用中并没有真正使用任何正则表达式,因此最好用 replace 替换它并省去双重转义的麻烦。
  • 同意,replace 是更好的选择。但是我从 java6 文档中找到了关于双重转义的很好的说明。 “请注意,替换字符串中的反斜杠 () 和美元符号 ($) 可能会导致结果与将其视为文字替换字符串时的结果不同。美元符号可能被视为对捕获的子序列的引用,如上所述,并且反斜杠用于转义替换字符串中的文字字符。”所以这就是双重转义背后的原因,replaceAll的第二个参数有点搞笑。
【解决方案2】:

我不知道这是否是原因,但请尝试将内部 IP 声明中的 . 更改为 \.

. in regexp 用于匹配所有内容。

【讨论】:

    【解决方案3】:

    我建议不要使用正则表达式执行过于复杂的 IP 体操。

    "([0-9]{1,3}.){3}[0-9]{1,3})" 进行一般检查是可以的,然后我会做一个

    "166.41.8.123".split ("\\.")
    

    之后是 Integer.parseInt 和范围检查或值比较。

    【讨论】:

      猜你喜欢
      • 2012-04-27
      • 1970-01-01
      • 2011-08-17
      • 2011-08-27
      • 2011-03-01
      • 2014-05-17
      • 1970-01-01
      • 2011-05-12
      • 1970-01-01
      相关资源
      最近更新 更多