我试图将字符串拆分为字符串数组,问题是.split()
也返回一个空元素。 ("test").split
会返回["","t","e","s","t"]
。
此问题中的解决方案Split string into array of character strings解决了问题(使用.split("(?!^)")
)。
但是我仍然无法理解为什么会这样,并且我不会使用一段我无法理解的代码,因为它完成了工作。
我已经阅读了关于负面预测的这两页http://www.regular-expressions.info/lookaround.html和http://ocpsoft.org/opensource/guide-to-regular-expressions-in-java-part-2/,但仍然无法理解。有人可以澄清一下吗?
答案 0 :(得分:5)
使用("test").split()
会将字符串拆分到字符前的每个位置,从而产生["", "t", "e", "s", "t"]
,因为第一次拆分(在t
之前)将导致空条目。
此正则表达式("(?!^)"
)的意思是:在每个字符处拆分字符串,其中不是行开头(^)是前一个字符 *:
你的字符串基本上看起来(对于Regex引擎)是这样的:^test$
因此,正则表达式将执行每个拆分,除了在第一个t
之前的拆分,因为它匹配^
- 当当前位置前面的字符为{时,它不应该拆分{1}}(String / Line-Start)。
* actualley ^
不是一个字符,这就是为什么你在^
之前没有另一个分裂 - 它们只是元字符 - 所以说。
答案 1 :(得分:2)
您需要先了解返回数组包含空第一个元素的原因。当您在索引0
处出现的分隔符上拆分字符串时,它也会在该分隔符上拆分。现在分隔符的左侧是一个空字符串,它是存储在数组索引0
的内容。
因此,以下代码将第一个数组元素作为空字符串:
"#ab#c".split("#"); // ["", "ab", "c"]
但是,如果#
不是字符串的第一个字符,则不会在索引0处获得空字符串。
现在,如果您不希望将空字符串作为第一个元素,则只需要避免在第一个#
上拆分。你会怎么做?通过使用否定的后视,确保您分组的#
不在字符串的开头 - ^
:
"#ab#c".split("(?<!^)#"); // ["ab", "c"]
当#
前面没有字符串(?<!^)
的开头时,此正则表达式会分开。 ^
表示字符串的开头,(?<!...)
表示负面的后视。
所以,现在你的分隔符本身就是一个空字符串。请记住,字符串在每个字符前面都包含一个空字符串,在最后一个字符之后也是如此。因此,简单地拆分空字符串,将拆分在第一个字符之前的分隔符上。你需要拆分空字符串,除了开头的字符串。用空字符串替换#
:
"abc".split("(?<!^)"); // ["a", "b", "c"]
同样,负面前瞻工作 - (?!^)
,但IMO,负面观察在这里更直观。
当然,如果您只想将字符串分解为字符数组,则可以使用String#toCharArray()
方法。
答案 2 :(得分:1)