2

我试图将一个字符串拆分为一个字符串数组,问题是它也.split()返回一个空元素。("test").split会回来["","t","e","s","t"]的。

这个问题中的解决方案将字符串拆分为字符串数组解决了这个问题(使用.split("(?!^)"))。

但是我仍然无法理解为什么会这样,而且我不会使用一段我无法理解的代码,因为它可以完成工作。

我已经阅读了这两页http://www.regular-expressions.info/lookaround.htmlhttp://ocpsoft.org/opensource/guide-to-regular-expressions-in-java-part-2/关于消极的前瞻,仍然无法理解。有人可以澄清一下吗?

4

3 回答 3

5

using("test").split()将在字符之前的每个位置拆分字符串,导致["", "t", "e", "s", "t"],因为第一个拆分(在 前面t)将导致一个空条目。

此正则表达式 ( "(?!^)") 确实意味着:在每个字符处拆分字符串,其中行首 (^) 不是前一个字符*:

你的字符串基本上看起来像这样(对于正则表达式引擎):^test$ 所以,正则表达式将执行每个拆分,除了第一个之前的拆分t,因为它匹配^- 并且它不应该拆分,当当前位置前面的字符是^(字符串/行开始)。

*actualley the^不是一个字符,这就是为什么你在 the 之前没有另一个拆分$- 它们只是元字符 - 可以这么说。

于 2013-10-21T19:46:39.370 回答
2

您需要首先了解为什么返回的数组包含一个空的第一个元素。当您在出现在 index 的分隔符上拆分字符串时0,它也会在该分隔符上拆分。现在分隔符的左侧是一个空字符串,它存储在0数组的索引处。

因此,以下代码会将第一个数组元素作为空字符串:

"#ab#c".split("#");  // ["", "ab", "c"]

但是,如果#不是字符串的第一个字符,您将不会在索引 0 处获得空字符串。

现在,如果您不希望空字符串作为第一个元素,您只需要避免在 first 上拆分#。你会怎么做?只需确保#您要拆分的不是在字符串的开头 - ^,方法是使用否定的后视:

"#ab#c".split("(?<!^)#");  // ["ab", "c"]

#此正则表达式在它前面没有字符串开头时拆分(?<!^)^表示字符串的开头,并(?<!...)表示负后视。


所以,现在你的分隔符本身就是一个空字符串。请记住,字符串在每个字符之前和最后一个字符之后都包含一个空字符串。因此,简单地拆分空字符串,将拆分第一个字符之前的分隔符。您宁愿需要拆分空字符串,但开头的字符串除外。替换#为空字符串:

"abc".split("(?<!^)");  // ["a", "b", "c"]

类似地,消极的前瞻工作 - (?!^),但 IMO,消极的后视在这里更直观。


当然,如果你只是想把字符串分解成一个字符数组,你可以使用String#toCharArray()method.

于 2013-10-21T19:48:55.757 回答
1

嗯,可能我不明白你的问题,但为什么不使用toCharArray()方法呢?

于 2013-10-21T19:48:14.713 回答