拆分字符串(特别是在Java中使用java.util.regex或其他东西)

时间:2009-05-07 19:07:00

标签: java regex split context-free-grammar

有没有人知道如何在字符上拆分字符串并考虑其转义序列?

例如,如果字符为':',则“a:b”分为两部分(“a”和“b”),而“a:b”则不分割。

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

提前谢谢你,

基达

2 个答案:

答案 0 :(得分:2)

(?<=^|[^\\]):让你关闭,但不会解决转义斜杠。 (这是一个文字的正则表达式,当然你必须逃避它中的斜线才能将它变成一个java字符串)

(?<=(^|[^\\])(\\\\)*):怎么样?我认为这应该满足任何':'之前的偶数斜杠。

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

答案 1 :(得分:2)

由于Java支持可变长度的后视(只要它们是有限的),你可以这样做:

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]);
        }

    }
}
  • (?<=(?<!\\)(?:\\\\){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));
}

奇怪的语法源于它需要在字符串的开头和结尾处理空片的情况。当一个匹配恰好为零个字符时,下一次尝试将在它结束后开始一个字符。如果没有,它将匹配另一个空字符串,另一个,无限制地......

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