gpt4 book ai didi

java - X?正则表达式量词无法按预期工作(我)

转载 作者:行者123 更新时间:2023-12-01 18:25:34 26 4
gpt4 key购买 nike

输入字符串:

  • aaa---foo---ccc---ddd
  • aaa---bar---ccc---ddd
  • aaa---------ccc---ddd

正则表达式:aaa.*(foo|bar)?.*ccc.*(ddd)

此正则表达式在任何情况下都找不到第一组 (foo|bar)。对于捕获组 1,它始终返回 null。我的问题是为什么以及如何避免这种情况。

这是我的正则表达式的非常简单的示例,仅用于演示。如果我删除 ? 量词,但输入字符串可以根本没有这个组(aaa--------ccc---ddd)并且我仍然需要确定它是foo还是bar还是null。但组 1 始终为 null

包含此正则表达式和测试字符串的页面:http://fiddle.re/45c766

最佳答案

这就是它不起作用的原因:当模式中有 .* 时,匹配器的算法将尝试匹配尽可能多的字符,以使模式的其余部分正常工作。在这种情况下,如果它尝试从字符串的整个剩余部分作为 .* 开始并删除一个字符直到匹配,它会发现 (对于 "aaa---foo--- ccc---ddd") 可以让 .* 匹配 9 个字符;那么 (foo|bar)? 不匹配任何内容,这是可以的,因为它是可选的;接下来的 .* 匹配 0 个字符,然后模式的其余部分匹配。所以这就是它选择的那个。

.*更改为.*的原因?:

aaa.*?(foo|bar)?.*?ccc.*(ddd)   

不起作用的是匹配器反向执行相同的操作。它从 0 个字符匹配开始,然后确定是否可以使该模式起作用。当它尝试这样做时,它会发现它可以使 .*? 匹配 0 个字符;那么 (foo|bar)? 不匹配任何内容;那么第二个 .*? 匹配 9 个字符;那么模式的其余部分匹配ccc---ddd。所以无论哪种方式,它都不会达到您想要的效果。

答案中有几个解决方案,都涉及前瞻。这是另一个解决方案:

aaa.*(foo|bar).*ccc.*(ddd)|aaa.*ccc.*(ddd)

这基本上按顺序检查两种模式;首先,它检查是否存在包含 foo|bar 的模式,如果不匹配,它将搜索另一种不包含 foo|bar 的可能性>。如果 foo|bar 存在的话,它总是会找到它。

不过,所有这些解决方案都涉及相当难以阅读的正则表达式。这就是我的编码方式:

Pattern pat1 = Pattern.compile("aaa(.*)ccc.*ddd");
Pattern pat2 = Pattern.compile("foo|bar");

Matcher m1 = pat1.matcher(source);
String foobar;
if (m1.matches()) {
Matcher m2 = pat2.matcher(m1.group(1));
if (m2.find()) {
foobar = m2.group(0);
} else {
foobar = null;
}
}

通常,尝试使用一个出色的正则表达式来解决问题会导致代码可读性较差(并且可能效率较低),而不仅仅是将问题分解为多个部分。

关于java - X?正则表达式量词无法按预期工作(我),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26346330/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com