【问题标题】:Is there an elegant way to do partial regex matches in Java?有没有一种优雅的方法可以在 Java 中进行部分正则表达式匹配?
【发布时间】:2009-09-30 04:35:53
【问题描述】:

我需要检查给定的字符串是否部分匹配给定的正则表达式。例如,对于正则表达式ab[0-9]c,字符串“a”、“ab”、“ab3”和“b3c”会“匹配”,但不会匹配字符串“d”、“abc”或“a3c”。我一直在做的是笨重的a(?:b(?:[0-9](?:c)?)?)?(它只适用于一些部分匹配,特别是那些“开始”匹配的),但由于这是 API 的一部分,我宁愿给用户一个输入匹配正则表达式的更直观的方式。

如果描述不是很清楚(我意识到可能不是!),这将用于验证文本框上的文本输入。我想防止任何会导致无效字符串的编辑,但我不能只将字符串与常规正则表达式匹配,因为在完全输入之前,它不会匹配。例如,使用上面的正则表达式 (ab[0-9]c),当我尝试输入 'a' 时,它是不允许的,因为字符串 "a" 与正则表达式不匹配。

基本上,它是一种反向startsWith(),适用于正则表达式。 (new Pattern("ab[0-9]c").startsWith("ab3") 应该返回 true。)

有什么想法吗?

【问题讨论】:

  • 仅供参考:a(?:b(?:[0-9](?:c)?)?)? 将匹配包含“a”的任何字符串,例如“jazz”。您想使用 ^a(?:b(?:[0-9](?:c)?)?)?$ 以便匹配整个字符串。
  • 客户端使用的所有正则表达式是否都像ab[0-9]c 一样简单,还是需要更复杂的匹配(即使用子组)?
  • 糟糕...是的,^ 和 $ 会自动添加到正则表达式中,这就是为什么我忽略添加它们的原因,谢谢。不,正则表达式并不是那么简单,它们可能会变得非常复杂,尽管不需要子组。

标签: java regex


【解决方案1】:

是 Matcher.hitEnd() 你在找什么?

Pattern thePattern = Pattern.compile(theRegexString);
Matcher m = thePattern.matcher(theStringToTest);
if (m.matches()) {
    return true;
}
return m.hitEnd();

【讨论】:

  • 不错!它几乎可以工作。它当然可以替代我目前正在做的事情。它仍然不适用于部分尾匹配(例如,“b3c”是ab[0-9]c 的部分尾匹配),但我当前的解决方案也不能处理这些。
  • 确实,hitEnd() 与 OP 将正则表达式分解为连续可选组的解决方案具有相同的目的。但是仍然无法检测到与正则表达式开头不一致的部分匹配。
【解决方案2】:

虽然可能有一些技巧可用,但从语义上讲,您的方式可能是最好的。它准确地描述了您正在寻找的内容。

但是,更大的问题是您是否真的需要在每次将字符输入到文本框中时都进行验证。为什么不能在最后验证一次并省去一些麻烦?

【讨论】:

  • “为什么”,确实... :( 因为客户 (tm) 如此规定。我这样做的方式存在问题,除了它非常不友好(我' d 必须向 API 的用户解释奇怪的部分匹配正则表达式等),是它不会匹配匹配正则表达式 END 的字符串。在上面的示例中,它不会匹配“3c ",这应该是有效的,因为您总是可以返回并在开头添加“ab”。
  • 客户是否真的指定它必须由正则表达式完成?还是设计的特定部分来自技术方面?
  • 客户没有指定它必须由正则表达式完成,这是我们的设计决定。最初它是通过简单的字符串匹配来完成的,但我们最终决定使用正则表达式,因为某些模式可能会变得非常复杂。
【解决方案3】:

这是一个可以解决您的特定示例的正则表达式:

^(?:a|b|[0-9]|c|ab|b[0-9]|[0-9]c|ab[0-9]|b[0-9]c|ab[0-9]c)?$

一般来说,如果您可以将正则表达式分解为原子部分,则可以将它们的所有可能分组“或”在一起,但它又大又丑。在这种情况下,有 4 个部分(a、b、[0-9] 和 c),因此您必须对 4+3+2+1=10 种可能性进行或运算。 (对于 n 部分,它是 (n×(n+1))/2 种可能性)。你也许可以通过算法生成这个,但测试起来会很痛苦。任何复杂的东西(比如子组)都很难正确处理。

更好的解决方案可能只是在输入字段旁边显示一条消息,告诉用户“信息不足”或其他内容,当他们正确时将其更改为绿色复选框或其他内容。这是 A List Apart 最近的一篇文章,它权衡了解决此问题的不同方法的优缺点:Inline Validation in Web Forms

【讨论】:

  • 这正是我试图避免的......笨拙的正则表达式(在您的示例中为 OR'ed,在我的示例中包含可选的子组)。 :( 不幸的是,客户无法接受您提出的更好的解决方案。他们需要的是阻止非法字符(不会导致有效字符串的非法含义字符)的文本输入,以及完全有效字符串的视觉反馈(意思是,正如实现的那样,当字符串完全匹配正则表达式时,文本框的背景会改变颜色)。
  • 也许你可以有两个步骤?一个只运行ab[0-9]c 并判断完整字符串是否有效,另一个运行大正则表达式来判断他们输入的内容是否可能有效。您可以在 keyPressed 事件上运行大正则表达式,如果失败,则返回 false(即不要让用户输入该字符)
  • 如果我可以通过算法生成这些正则表达式,那将是一个有效的解决方案。为简单的正则表达式生成它们应该不是什么大问题,但不幸的是,并非所有使用的正则表达式都很简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多