如何使用正则表达式拆分字符串?

时间:2017-10-30 11:58:55

标签: java regex split

我想实现Java中的String.split()方法,但不是通过调用split()方法。

例如,调用“逗号,分隔,值”.split(“,”, - 1)将为我提供3个值。现在我想实现同样的目的,但是使用正则表达式,而不是调用split()方法。

分隔符是任意的(可以包含多个字符),分割的值也应该是任意的。

我已尝试搜索之前的StackOverflow答案,人们建议使用否定前瞻,但我还没有找到适用于任意分隔符和值的精确正则表达式。

提前致谢。

PS:即将构造正则表达式时,“任意”分隔符是已知的。它作为参数传递给regex构建器。它可以是逗号,管道或多个字符的组合,例如pipe-tilde-pipe。

我理解split()本身接受正则表达式作为参数。为了说清楚,我想要的是这样的:

Pattern pattern = Pattern.compile("<the regex pattern>");
Matcher matcher = pattern.matcher("comma,separated,values");
while (matcher.find()) {
  System.out.println(matcher.group());
}

以下内容将打印出来:

  • 逗号
  • 分离

1 个答案:

答案 0 :(得分:0)

一旦找到sep或者线本身结束,值就会包含任何字符和结尾。使用惰性*?,因此您只能转到第一个 sep(否则您将首先运行到EOL并匹配$):< / p>

.*?(<sep>|$)

值不包含分隔符,因此请使用捕获组单独获取它:

(.*?)(<sep>|$)

当迭代匹配时,find()将使用该值,将其放入捕获组1(使用group(1)访问),然后使用分隔符,因此第二次调用{ {1}}找到下一个值和下一个分隔符。 find()可以是任何正则表达式;如果你想拆分一个普通的字符串,你必须首先逃避它以确保安全。另外,如果你使用sep作为正则表达式,请注意贪婪。

例如:设置sep,它匹配可被sep = ([0369]|([258][0369]*[147])|([147]|[258]{2})([0369]|([147][0369]*[258]))*([258]|[147]{2}))+整除的数字。然后

3

打印

Pattern pat = Pattern.compile("(.*?)(([0369]|([258][0369]*[147])|([147]|[258]{2})([0369]|([147][0369]*[258]))*([258]|[147]{2}))+|$)");
Matcher mat = pat.matcher("a333521c63");
while(mat.find()) {
    System.out.println("Field: " + mat.group(1) + "; Terminated by: " + mat.group(2));
}

请注意,如果您必须使用Field: a; Terminated by: 333 Field: 5; Terminated by: 21 Field: c; Terminated by: 63 Field: ; Terminated by: (又名group())而不是group(0),那么您必须使用lookarounds,这会产生此正则表达式

group(1)

由于(?<=<sep>|^).*?(?=<sep>|$) 位于lookbehind内,因此您无法在其中使用sep+*,因为它是Java regex引擎的限制,它不能处理潜在无限大小的外观(公平地说,大多数其他引擎更具限制性)。它适用于您的简单用例,逗号和固定字符串

{n,}

它甚至适用于此:

Commas: (?<=,|^).*?(?=,|$)
|~|   : (?<=\|~\||^).*?(?=\|~\||$)

但它不适用于数字 - 可分割 - Snake : (?<=s{0,10}!|^).*?(?=s{0,10}!|$)

3

示例:

Div-by-3: (?<=([0369]|([258][0369]*[147])|([147]|[258]{2})([0369]|([147][0369]*[258]))*([258]|[147]{2}))+|^).*?(?=([0369]|([258][0369]*[147])|([147]|[258]{2})([0369]|([147][0369]*[258]))*([258]|[147]{2}))+|$)
                                  ^ ERROR! * in lookbehind

输出:

Pattern asSeparator(String sep) {
    return Pattern.compile("(?<=(" + sep + ")|^).*?(?=(" + sep + ")|$)");
}
String[] seps = { ","
                , "\\|~\\|"
                , "s{0,10}!"
                , "([0369]|([258][0369]*[147])|([147]|[258]{2})([0369]|([147][0369]*[258]))*([258]|[147]{2}))+"
                };
for(String sep : seps) {
    System.out.println("Separator: " + sep);
    Pattern pat = asSeparator(sep);
    Matcher mat = pat.matcher("a3a,|~|, sssss!6");
    while(mat.find()) {
        System.out.println(mat.group());
    }
    System.out.println();
}