java - 正则表达式所有格量词

标签 java regex

我在回答 this question , here是指向我的答案的直接链接。

你会注意到我使用了这个模式:

(\\?)?&?(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)

最佳答案

我想,这与所有格量词的工作方式有关。首先,它们像贪婪量词一样工作。从某种意义上说,他们会尽可能多地匹配。但与贪心量词不同的是,一旦匹配到某些东西,回溯后不会放弃匹配。

所以,使用你的正则表达式:

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

它首先找到 username 之前的 ?,所以它匹配它并将其存储在组 1 中。然后它找到下一个字符 &usernameu 不匹配。所以它回溯,并在 ? 处停止。由于那是作为所有格量词匹配的,因此他们不会丢失匹配项。

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

&TXT{UE-IP,UE-Username,UE-Password}&

哪里因为 ? 是可选的,所以不匹配。但它不会替换第 1 组中的任何内容。

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


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

关于java - 正则表达式所有格量词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22557708/

相关文章:

json - 用尖叫 Frog 提取Json数据

regex - 何时在 'perl=TRUE'中设置 'strsplit'不起作用(按预期或完全无效)?

java - 我的 Intset 类有什么问题吗?

java - 绑定(bind)到 Android 库中定义的远程服务失败

java - JTable 搜索结果列表

javascript - 用空 javascript 替换 <xml> 标签数据

php - Twitter 解析文本中的方形符号

python - 匹配一个单词,后跟任意顺序的两个可选组

java - 使用多个排序键查询 Dynamodb

java - 寻求有关 JVM 随机崩溃的帮助