1

假设您有一个像这样的正则表达式:

\d+\.?\d* (mg |teaspoon |mcg |tablet |units |puffs |tab )*(\d )*(P\.O\. )*((once )*daily|B\.I\.D\.*|(once )*a day|Q\.I\.D\.|nightly|P\.R\.N\.|T\.I\.D\.|every (other )*(day|morning))

它匹配各种表达式,包括:

1 茶匙 每日一次
1.5 毫克
10 毫克 每晚 1 次 PO

等等

我想了解的是,假设每天 1.5 毫克和 1.5 毫克是匹配的,java 正则表达式是否总是匹配最长的字符串?

4

3 回答 3

2

使用您当前拥有的表达式,它实际上与“1.5 mg”不匹配,因为定义频率的最后一组不是可选的。

为了更笼统地回答您的问题,如果您有一个与正则表达式匹配的字符串,并且该字符串的子字符串也将匹配,则完全取决于将匹配哪个正则表达式

例如,对于字符串“foobar”,您将使用 regex 匹配整个字符串foo(bar)*,但只会将“foo”与 regex 匹配foo(bar)*?

如果要确保始终匹配最大的字符串,请确保在交替时始终将较长的元素放在首位,例如,(foobar|foo)而不是(foo|foobar). 您可能还希望避免使用延迟重复,如*?,+???.

当然,这些只是一些一般性的指导方针,彻底测试和重构你的正则表达式,直到你在所有情况下都得到预期的结果。

于 2013-04-23T21:45:59.233 回答
1

java 正则表达式是否总是匹配最长的字符串?

不,正则表达式并不总是匹配最长的字符串,因为正则表达式库通常会在找到匹配项后停止,而无需回溯以查找更长的匹配项。

例如,

Pattern p = Pattern.compile("a|aa");
Matcher m = p.matcher("aaa");
while (m.find()) { System.out.println(m.group()); }

将打印

a
a
a

不是

aa
a

这也会影响组匹配。

这会导致混淆的一个地方是当人们尝试使用正则表达式来匹配按字母顺序排列的标识符列表时,执行类似的操作

Pattern.compile("<(/?)(a|b|p|pre|s|script)[^>]*>")

匹配标签。给定输入"<script>Not text in an s tag</script>",第 2 组将包含"s",而不是"script"

于 2013-04-23T21:40:44.660 回答
1

在这种情况下,如果模式的其余部分与较长的字符串匹配,则将返回最长的字符串,而不是最短的。

public static void main(String[] args) {
    String regex = "\\d+.?\\d* (mg |teaspoon |mcg |tablet |units |puffs |tab )(\\d )(P.O. )*((once )daily|B.I.D.|(once )a day|Q.I.D.|nightly|P.R.N.|T.I.D.|every (other )(day|morning))";

    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher("1.5 mg 10 mg 1 P.O. nightly");
    while(m.find()){
        System.out.println(m.group());
    }

}

打印:每晚 10 毫克 1 次 PO

于 2013-04-23T21:44:03.407 回答