【问题标题】:Trouble implementing partial matches with regular expression on Android在 Android 上使用正则表达式实现部分匹配时遇到问题
【发布时间】:2011-08-16 21:41:35
【问题描述】:

我正在创建一个正则表达式来评估 IP 地址是否是有效的多播地址。此验证在您键入时实时发生(如果您键入无效/超出范围的字符,则不接受),因此我不能简单地根据正则表达式评估最终结果。我遇到的问题是它允许在每组数字(224..、224.0..、224.0.0.. 都显示为有效)之后有一个双句点。

下面的代码是正在发生的事情的静态表示。不知何故 224.. 显示为合法值。我已经在线测试了这个正则表达式(非 java 化:^2(2[4-9]|3\d)(.(25[0-5]|2[0-4]\d|1\d \d|[1-9]\d|\d)){3}$ ) 并且它完美地工作并且不接受我正在描述的无效输入。

Pattern p = Pattern.compile("^2(2[4-9]|3\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
Matcher m = p.matcher("224..");


if (!m.matches() && !m.hitEnd()) {
    System.out.println("Invalid");
} else {
    System.out.println("Valid");
}

每当我输入 224.. 时,似乎 m.hitEnd() 方法的评估结果为真,这对我来说没有意义。 如果有人可以请检查一下并确保我没有犯任何明显的错误,也许可以解释为什么在这种情况下 hitEnd() 返回 true 我会很感激。 谢谢大家。

【问题讨论】:

  • 首先,m.matches() 始终匹配完整的输入,因此您不需要以 ^ 开始您的表达式。接下来,m.hitEnd() 表示正则表达式引擎命中输入结尾,这不一定意味着您的正则表达式匹配到输入结尾。
  • 以下问题似乎暗示stackoverflow.com/questions/2469231/…
  • @dma_k: hitEnd() 表示正则表达式匹配,但输入不足;有了更多的输入,就有可能实现匹配(或者,如果确实匹配,则可能实现 longer 匹配)。类似于 Boost.Regex 中的partial matching

标签: java android regex dalvik


【解决方案1】:

在对自己进行了一些评估之后(发现这是在 Android 上),我意识到相同的代码在 Dalvik 上的响应与在常规 JVM 上的响应不同。

代码是:

   Pattern p = Pattern.compile("^2(2[4-9]|3\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
    Matcher m = p.matcher("224..");

    if (!m.matches() && !m.hitEnd()) {
        System.out.println("Invalid");
    } else {
        System.out.println("Valid");
    }

这段代码(尽管稍作修改)在 Android 上打印 Valid,在 JVM 上打印 Invalid。

【讨论】:

  • 我已在code.google.com/p/android/issues/detail?id=19308 提交了一个问题,希望能调查此事。
  • 已验证这是错误。这就是为什么自从我在 Android 上运行它以来,其他人似乎得到的结果都与我不同。
【解决方案2】:

我不知道您是如何测试您的正则表达式的,但根据您的描述,它看起来不正确。

您的正则表达式需要所有 4 个数字部分。它不可能匹配 224 .. 只有 [0-1] 和 \d 标有问号,因此是可选的。

因此,在不处理允许的特定数字限制的细节的情况下,我建议您这样做:

^\\d{1-3}\\.(\\d{0-3}\\.)?(\\d{0-3}\\.)?(\\d{0-3}\\.)?$

而且你不必使用 hitEnd(): $ 最后就足够了。并且不要使用matches()。请改用find()matches() 类似于 find(),但会自动添加 ^ 和 $。

【讨论】:

  • 224. 不匹配,但仍是潜在匹配;这就是hitEnd() 的意思。但是,再添加一个点(224..),就没有匹配的可能性了; matches()hitEnd() 都应该返回 false。但似乎hitEnd() 忽略了第二个点。
【解决方案3】:

我刚刚测试了您的代码,m.hitEnd() 对我的评估结果为 false,我收到无效...

所以我不确定这里的问题是什么?

【讨论】:

    【解决方案4】:

    我在 Dalvik 报告了bug 20625。在此期间,您不需要使用hitEnd(),拥有$ 后缀就足够了。

    public void testHitEnd() {
      String text = "b";
      String pattern = "^aa$";
      Matcher matcher = Pattern.compile(pattern).matcher(text);
      assertFalse(matcher.matches());
      assertFalse(matcher.hitEnd());
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      • 2022-06-10
      • 2019-02-02
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多