正则表达式具有量词

时间:2014-03-21 11:37:23

标签: java regex

我正在回答this questionhere是我答案的直接链接。

您会注意到我使用了模式:

(\\?)?&?(TXT\\{[^}]++})(&)?

在以下代码中(添加了一些与我的问题相关的调试):

public static void main(final String[] args) throws Exception {
    final String[] loginURLs = {
        "http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}",
        "http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&TXT{UE-IP,UE-Username,UE-Password}",
        "http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}&username=abcd&location={LOCATION}&password={PASS}",
        "http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}",
        "http://ip:port/path?username=abcd&password={PASS}"};
    final Pattern patt = Pattern.compile("(\\?)?&?(TXT\\{[^}]++})(&)?");
    for (final String loginURL : loginURLs) {
        System.out.printf("%1$-10s %2$s%n", "Processing", loginURL);
        final StringBuffer sb = new StringBuffer();
        final Matcher matcher = patt.matcher(loginURL);
        while (matcher.find()) {
            final String found = matcher.group(2);
            System.out.printf("%1$-10s 1:%2$s,3:%3$s%n", "Groups", matcher.group(1), matcher.group(3));
            System.out.printf("%1$-10s %2$s%n", "Found", found);
            if (matcher.group(1) != null && matcher.group(3) != null) {
                matcher.appendReplacement(sb, "$1");
            } else {
                matcher.appendReplacement(sb, "$3");
            }
        }
        matcher.appendTail(sb);
        System.out.printf("%1$-10s %2$s%n%n", "Processed", sb.toString());
    }
}

其中输出为:

Processing http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}
Groups     1:null,3:&
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}

Processing http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&TXT{UE-IP,UE-Username,UE-Password}
Groups     1:null,3:null
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}

Processing http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}&username=abcd&location={LOCATION}&password={PASS}
Groups     1:?,3:&
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}

Processing http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}
Groups     1:?,3:null
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path

Processing http://ip:port/path?username=abcd&password={PASS}
Processed  http://ip:port/path?username=abcd&password={PASS}

哪个是完美的。

现在,我的问题

当我更改第一个匹配组(\\?)?时,要使用占有量词,即(\\?)?+第一个项的输出将变为:

Processing http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}
Groups     1:?,3:&
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}?password={PASS}

在第一场比赛组中的问号来自 的生活中我无法解决

我没有看到模式正确匹配所需字符串的方法,并在第一组中抓取问号。

我只是错过了一些明显的东西吗?

如果重要,我正在运行OS X Mavericks:

java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

1 个答案:

答案 0 :(得分:3)

我想,这与占有量量词的工作原理有关。首先,他们像贪婪的量词一样工作。从某种意义上说,他们会尝试尽可能多地匹配。但与贪婪的量词不同,一旦他们匹配某些东西,他们就会在回溯后不会放弃这场比赛。

所以,拿你的正则表达式:

"(\\?)?+&?(TXT\\{[^}]++})(&)?"

它首先在?之前找到username,因此它与之匹配并将其存储在第1组中。然后它会发现下一个字符&u不匹配{1}}的{​​1}}。所以它回溯,并停在username。由于这被称为占有量词,他们不会松开比赛。

现在,它进一步发展。此时,组1仍包含?。现在它匹配部分:

?

由于&TXT{UE-IP,UE-Username,UE-Password}& 是可选的,因此不匹配。但它并没有取代第1组中的任何东西。

这意味着,您从第一次匹配的第1组获得?


这似乎是Java正则表达式引擎中的一个错误,就像Perl一样,该组未定义。 Here's the fiddle