【问题标题】:Splitting a String (especially in Java with java.util.regex or something else)拆分字符串(尤其是在 Java 中使用 java.util.regex 或其他东西)
【发布时间】:2009-05-07 19:07:00
【问题描述】:

有谁知道如何根据转义序列在字符上拆分字符串?

例如,如果字符是':',则“a:b”被分成两部分(“a”和“b”),而“a:b”根本不被分割。

我认为这很难(不可能?)与正则表达式有关。

提前谢谢你,

凯达

【问题讨论】:

标签: java regex split context-free-grammar


【解决方案1】:

由于 Java 支持可变长度的look-behinds(只要它们是有限的),您可以这样做:

import java.util.regex.*;

public class RegexTest {
    public static void main(String[] argv) {

        Pattern p = Pattern.compile("(?<=(?<!\\\\)(?:\\\\\\\\){0,10}):");

        String text = "foo:bar\\:baz\\\\:qux\\\\\\:quux\\\\\\\\:corge";

        String[] parts = p.split(text);

        System.out.printf("Input string: %s\n", text);
        for (int i = 0; i < parts.length; i++) {
            System.out.printf("Part %d: %s\n", i+1, parts[i]);
        }

    }
}
  • (?&lt;=(?&lt;!\\)(?:\\\\){0,10}) 在后面查找偶数个反斜杠(包括零,最多 10 个)。

输出:

Input string: foo:bar\:baz\\:qux\\\:quux\\\\:corge
Part 1: foo
Part 2: bar\:baz\\
Part 3: qux\\\:quux\\\\
Part 4: corge

另一种方法是匹配部分本身,而不是在分隔符处拆分。

Pattern p2 = Pattern.compile("(?<=\\A|\\G:)((?:\\\\.|[^:\\\\])*)");
List<String> parts2 = new LinkedList<String>();
Matcher m = p2.matcher(text);
while (m.find()) {
    parts2.add(m.group(1));
}

奇怪的语法源于它需要处理字符串开头和结尾处的空片段的情况。当匹配恰好跨越零个字符时,下一次尝试将开始一个字符超过它的结尾。如果没有,它将匹配另一个空字符串,以及另一个,无限……

  • (?&lt;=\A|\G:) 将在后面查找字符串的开头(第一段)或上一个匹配的结尾,然后是分隔符。如果我们使用(?:\A|\G:),如果第一部分为空(输入以分隔符开头),它将失败。
  • \\. 匹配任何转义字符。
  • [^:\\] 匹配任何不在转义序列中的字符(因为 \\. 消耗了这两个字符)。
  • ((?:\\.|[^:\\])*) 捕获所有字符,直到第一个非转义分隔符进入捕获组 1。

【讨论】:

    【解决方案2】:

    (?&lt;=^|[^\\]): 让你接近,但不解决转义的斜杠。 (这是一个文字正则表达式,当然你必须转义其中的斜杠才能将其转换为 java 字符串)

    (?&lt;=(^|[^\\])(\\\\)*): 那怎么样?我认为这应该满足前面有偶数个斜杠的任何 ':'。

    编辑:不要对此投赞成票。 MizardX 的解决方案更好:)

    【讨论】:

    • 关键是 (?
    • MizardX 指出后视需要有一个有限的长度。我的没有,所以我想它不起作用(尚未测试)。我相信我们的解决方案在其他方面是相似的。他可能更好,因为它使用负后视来检查非斜杠字符,而我使用“^|[^\\]”,它在多行场景中可能会或可能不会有不同的行为(不确定)。
    • (^|[^\\]) 应该可以工作。 ^ 可能匹配行的开头而不是字符串。没关系,因为它仍然保证它不是反斜杠。 [^\\] 也会匹配换行符,所以在不使用多行模式时也没有问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多