Java .split方法匹配空字符串奇怪的行为

时间:2015-01-30 22:21:02

标签: java regex string split

我想从字符序列中获取数字列表(即:字母和数字)。所以我写了这段代码:

class A {
  public static void main(String[] args) {
    String msg = "aa811b22";
    String[] numbers = msg.split("\\D+");
    for (int i = 0; i < numbers.length; i++) {
      System.out.println(">" + numbers[i] + "<");
    }

  }
}

超越它运行......:

 $ java A
><
>811<
>22<

好的,所以它以某种方式匹配空字符串......我向自己解释说""(空字符串)实际上匹配NON DIGIT MATCHER的正则表达式\D+。什么都不是数字......对吧? (但是......为什么它只返回1个空字符串?任何字符串中都有无限(∞)个空字符串)

为了确保自己,我尝试从上面给出的字符串中提取单词:

class A {
  public static void main(String[] args) {
    String msg = "aa811b22";
    String[] words = msg.split("\\d+");
    for (int i = 0; i < words.length; i++) {
      System.out.println(">" + words[i] + "<");
    }

  }
}

实际打印出我期望的内容(没有返回空字符串):

 $ run A
>aa<
>b<

但是......我做了一些让我完全糊涂的测试:

System.out.println("a".split("\\D+").length);
#=> 0 (WHY NOT 1? Empty string shouldn't be here?!)
System.out.println("a1".split("\\D+").length);
#=> 2 (So now it splits to empty string and 1)
System.out.println("1a".split("\\D+").length);
#=> 1 (now it returns expected "a" string)

所以我的问题是:

  • 为什么split会使用我给出的示例返回空字符串?
  • 为什么"a".split("\\D+").length会返回0?
  • 为什么"a1".split("\\D+").length是2(但没有人)
  • "1a".split("\\D+").length)"a1".split("\\D+").length)的差异 在拆分的情况下?

2 个答案:

答案 0 :(得分:2)

  • 为什么split会使用我给出的示例返回空字符串?

'a'不是数字,因此aa是分隔符。在分隔符的两侧都有要返回的元素,空字符串位于a的左侧。如果分隔符为",",那么在字符串",a,b"之外,您会看到3个元素 - """a""b"。在这里,aa是分隔符,就像我的示例中的,一样。

  • 为什么"a".split("\\D+").length会返回0?

'a'不是数字,因此它是一个分隔符。分隔符的存在意味着在String的任一侧有两个子字符串从原始a中分离出来,两个空字符串。但是,no-arg split method会丢弃尾随空字符串。它们全部为空,因此它们全部被丢弃,length0

  • 为什么"a1".split("\\D+").length是2(但不是1)

仅丢弃尾随空字符串,因此元素为"""1"

  • "1a".split("\\D+").length"a1".split("\\D+").length的区别在于分裂?

"1a"将丢弃一个尾随空字符串,但"a1"将不会丢弃尾随空字符串(它的前导)。

答案 1 :(得分:1)

它与空字符串不匹配。相反,它将字符串开头的"aa"作为分隔符进行匹配。第一个元素为空,因为在第一个分隔符之前只有一个空字符串。相反,对于尾随分隔符,没有返回空字符串,如documentation for split()中所述:

  

此方法的工作方式就像通过调用双参数split方法一样   给定的表达式和一个零的限制参数。 尾随空   因此,字符串不包含在结果数组中。