【问题标题】:Can you use zero-width matching regex in String split?您可以在字符串拆分中使用零宽度匹配正则表达式吗?
【发布时间】:2011-01-25 06:50:36
【问题描述】:
System.out.println(
    Arrays.deepToString(
        "abc<def>ghi".split("(?:<)|(?:>)")
    )
);

这打印出[abc, def, ghi],就好像我在"&lt;|&gt;" 上分裂了一样。我希望它打印[abc, &lt;def&gt;, ghi]。有没有办法使用一些正则表达式来完成我想要的?


也许是一个更简单的例子:

System.out.println(
    Arrays.deepToString(
        "Hello! Oh my!! Good bye!!".split("(?:!+)")
    )
);

这将打印[Hello, Oh my, Good bye]。我希望它打印[Hello!, Oh my!!, Good bye!!]。 `.

【问题讨论】:

标签: java regex split delimiter


【解决方案1】:

你需要看看零宽度匹配结构:

(?=X)   X, via zero-width positive lookahead
(?!X)   X, via zero-width negative lookahead
(?<=X)  X, via zero-width positive lookbehind
(?<!X)  X, via zero-width negative lookbehind

【讨论】:

  • 是的,我误解了(?:...) 的用途。
【解决方案2】:

您可以使用\b(字边界)作为要查找的内容,因为它是零宽度,并将其用作查找&lt; 和&gt; 的锚。

String s = "abc<def>ghi";
String[] bits = s.split("(?<=>)\\b|\\b(?=<)");
for (String bit : bits) {
  System.out.println(bit);
}

输出:

abc
<def>
ghi

现在这不是一个通用的解决方案。您可能需要为此编写一个自定义拆分方法。

您的第二个示例表明您所追求的并不是真正的split(),而是一个正则表达式匹配循环。例如:

String s = "Hello! Oh my!! Good bye!!";
Pattern p = Pattern.compile("(.*?!+)\\s*");
Matcher m = p.matcher(s);
while (m.find()) {
  System.out.println("[" + m.group(1) + "]");
}

输出:

[Hello!]
[Oh my!!]
[Good bye!!]

【讨论】:

  • 您能否对我的回答发表评论,看看有什么问题吗?谢谢。
【解决方案3】:

感谢 Cine 提供的信息,我认为这些是我正在寻找的答案:

System.out.println(
    Arrays.deepToString(
        "abc<def>ghi<x><x>".split("(?=<)|(?<=>)")
    )
); // [abc, <def>, ghi, <x>, <x>]


System.out.println(
    Arrays.deepToString(
        "Hello! Oh my!! Good bye!! IT WORKS!!!".split("(?<=!++)")
    )
); // [Hello!,  Oh my!!,  Good bye!!,  IT WORKS!!!]

现在,第二个是通过尝试所有不同的量词诚实地发现的。贪婪和不情愿都不会起作用,但占有欲会起作用。

我还是不知道为什么。

【讨论】:

  • 你的第二个例子不应该工作。 :-/ 它应该抛出 PatternSyntaxException,因为后视没有明显的最大长度。您的正则表达式编译是一个错误;它有效令人难以置信——而且不值得依赖。这是您应该使用的:(?&lt;=!)(?!!)。这适用于任何支持前瞻和后瞻的正则表达式风格。
  • 该错误已被报告,如果这就是您的意思。我建议你在任何情况下都不要养成在lookbehinds中使用可变宽度表达式的习惯;很少有正则表达式支持该功能,而且通常有更好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 2020-04-13
  • 2017-01-09
相关资源
最近更新 更多