你能在String split中使用零宽度匹配正则表达式吗?

时间:2010-03-09 04:16:52

标签: java regex split delimiter

System.out.println(
    Arrays.deepToString(
        "abc<def>ghi".split("(?:<)|(?:>)")
    )
);

这会打印[abc, def, ghi],就像我在"<|>"上分开一样。我想要它打印[abc, <def>, ghi]。有没有办法运用一些正则表达式的魔法来完成我想要的东西?


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

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

这会打印[Hello, Oh my, Good bye]。我想要它打印[Hello!, Oh my!!, Good bye!!]。 `。

3 个答案:

答案 0 :(得分:3)

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

(?=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

答案 1 :(得分:1)

您可以使用\b(字边界)作为查找内容,因为它是零宽度,并将其用作查找<>的锚点。

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!!]

答案 2 :(得分:0)

感谢来自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!!!]

现在,第二个是通过试验所有不同的量词来诚实地发现的。无论是贪婪还是不情愿的工作,都是占有欲的。

我仍然不确定原因。