【问题标题】:Java splitting a string into characters using negative look-ahead [duplicate]Java使用负前瞻将字符串拆分为字符[重复]
【发布时间】:2013-10-21 19:42:00
【问题描述】:

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

这个问题Split string into array of character strings的解决方案解决了这个问题(使用.split("(?!^)"))。

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

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

【问题讨论】:

  • 为什么不使用String#toCharArray();
  • 程序中使用的其中一个类中有一个属性被定义为String,该属性用于与输入的字母进行比较。

标签: java regex string split


【解决方案1】:

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

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

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

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

【讨论】:

  • 现在我明白了,感谢您简洁明了的回答。
【解决方案2】:

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

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

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

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

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

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

当该正则表达式前面没有字符串 (?&lt;!^) 的开头时,它会在 # 上拆分。 ^ 表示字符串的开头,(?&lt;!...) 表示否定的look-behind。


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

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

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


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

【讨论】:

    【解决方案3】:

    嗯,可能我没看懂你的问题,为什么不用toCharArray()方法呢?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-24
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 2013-08-19
      相关资源
      最近更新 更多