您可以在字符串拆分中使用零宽度匹配正则表达式吗?

Posted

技术标签:

【中文标题】您可以在字符串拆分中使用零宽度匹配正则表达式吗?【英文标题】: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!!]。 `.

【问题讨论】:

重复***.com/questions/275768/… 【参考方案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中使用可变宽度表达式的习惯;很少有正则表达式支持该功能,而且通常有更好的方法。

以上是关于您可以在字符串拆分中使用零宽度匹配正则表达式吗?的主要内容,如果未能解决你的问题,请参考以下文章

偷学Python第三十一天:Python正则表达式的语法以及re模块的使用

js正则

正则断言详解

正则表达式匹配规则

正则表达式入门环视

在 C# 字符串中摆脱零宽度空间的最简单方法