【问题标题】:Java string - split on space, but preserve double spaceJava 字符串 - 按空格分割,但保留双倍空格
【发布时间】:2012-07-03 18:19:15
【问题描述】:

目前我正在用空格分割一个字符串。但是,当我将它们全部重新组合在一起时,我想保留一些双重空格。有关如何执行此操作的任何建议?

即字符串"I went to the beach. I ate pie" 被拆分为

I
went
to
the
beach.

I
ate
pie

我不想要空白条目,但我想将它们重新组合成相同的格式。谢谢大家!

【问题讨论】:

  • 对我来说听起来你可以使用 StringTokenizer (由空格分隔),只需在任何非字母字符上附加一个空格。
  • 你能保留每个标记末尾的空格吗?那将有一个非常简单的编程解决方案。

标签: java string split


【解决方案1】:

执行 String replaceAll(" ", "likelyCharacterSequence") 然后像往常一样用空格分割你的字符串。然后,您可以通过将 {unlikelyCharacterSequence} 替换为末尾的“”来转换回双倍空格。

但是:如果您在未修改的实际字符串中遇到“不太可能”的字符序列,这将失败。如需更通用的解决方案,请查看此示例下方列出的替代方案。

示例(警告,取决于不存在 !@#!@# :

String example = "Hello.  That was a double space. That was a single space."
String formatted = example.replace("  ", " !@#!@#");
String [] split = formatted.split(" ");
for(int i = 0; i < split.length; i++)
{
  split.replace("!@#!@#", " ");
}
// Recombine your splits?

或者,您可以采取更强大的策略来重新组合您在问题中使用的字符串,但忽略仅包含一个空格的元素:

String example = "ThisShouldBeTwoElements.  ButItIsNot.";
String [] splitString = example.split(" ");
String recombined = "";
for(int i = 0; i < splitString.length; i++)
{
  if(!splitString[i].equals(" "))
    recombined += splitString[i];
}

【讨论】:

  • 如果字符串包含字符 % 怎么办?
  • 好点!尝试选择一个不在字符串中的字符,否则我会想出一个更好的解决方案并对其进行编辑。
  • @KingsIndian 所以将 % 替换为 %%% :)))
  • 修复了更一般的情况。我认为包含 {!@#!@#} 的字符串在大多数应用程序中是不太可能的。
  • @BlackVegetable,你{!@#@!#}疯了。 :P
【解决方案2】:
String st = "I went to the beach.  I ate pie";
st.split("\\s{1}(?!\\s)");

这会导致

[I, went, to, the, beach. , I, ate, pie]

我还建议查看http://docs.oracle.com/javase/6/docs/api/ 和/或http://www.regular-expressions.info/java.html,以便了解这是在做什么。

【讨论】:

    【解决方案3】:

    好好看看 Java 的 Regex 可以为您做什么。有一种方法可以使用正则表达式来识别模式。

    Java regex examples

    【讨论】:

      【解决方案4】:

      试试这个,它应该删除非空白字符之间的所有空白。

      myString = myString.replaceAll("\S\s\S", "");
      

      这将在两个单词之间出现多次空格时保留空格。

      【讨论】:

        【解决方案5】:

        我知道这是一个老问题,但为了未来观众的利益:您正在寻找的概念是“捕获组”。捕获组允许您引用表达式中的匹配项并在以后检索它们,例如通过反向引用,而不是吞下字符串。

        从文档中,您需要了解以下相关语法:

        (?<name>X)          X, as a named-capturing group
        (?:X)               X, as a non-capturing group
        (?idmsuxU-idmsuxU)  Nothing, but turns match flags i d m s u x U on - off
        (?idmsux-idmsux:X)  X, as a non-capturing group with the given flags i d m s u x on - off
        (?=X)               X, via zero-width positive lookahead
        (?!X)               X, via zero-width negative lookahead
        (?<=X)              X, via zero-width positive lookbehind
        (?<!X)              X, via zero-width negative lookbehind
        (?>X)               X, as an independent, non-capturing group
        

        使用输入文本:

        String example = "ABC     DEF     GHI J K";
        

        您可以使用正负前瞻组合将尾随空格与每个单词组合起来:

        // Result: [ABC     , DEF     , GHI , J , K]
        example.split("(?<=\\s+)(?!\\s)");
        

        或者您可以使用正向前瞻来捕获单词边界,以将空格保留为单独的分组元素:

        // Result: [ABC,      , DEF,      , GHI,  , J,  , K]
        example.split("(?=\\b)");
        

        Java 模式 API:
        http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html



        旁注:虽然“用完全不可信的东西替换文本”的建议很诱人,因为它很容易,但不要 曾经在生产代码中这样做。它最终失败,而且它发生的频率比你想象的要多。在一名程序员使用了大约 80 列“~=$~=$~=$...”并认为这是安全的之后,我调试了一个呼叫中心。这持续了几个月,直到一位服务代表用这个序列在他的笔记上保存了一个“花哨的边界”。我什至在搜索服务器上目睹了真正的随机 MD5 冲突。诚然,MD5 碰撞花了 11 年时间,但它仍然使搜索崩溃,重点仍然存在。 唯一的字符串永远不会。始终假设会出现重复项。

        【讨论】:

          猜你喜欢
          • 2018-10-23
          • 2013-10-11
          • 2012-08-03
          • 1970-01-01
          • 1970-01-01
          • 2011-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多