【问题标题】:Splitting a string with a certain pattern in Java在 Java 中分割具有特定模式的字符串
【发布时间】:2014-09-06 19:03:57
【问题描述】:

我正在为包含以下字符串模式的文件编写解析器:

Key : value
Key : value
Key : value
etc...

我能够将这些行一一检索到一个列表中。我想做的是将每个字符串的键与值分开。我知道有 split() 方法可以采用正则表达式并为我执行此操作,但我对它们非常不熟悉,所以我不知道将什么正则表达式作为参数提供给 split() 函数。

此外,虽然不在我正在解析的文件的规范中,但我希望该正则表达式也能够识别以下模式(如果可能的话):

Key: value
Key :value
Key:value
etc...

所以基本上,无论: 字符之前/之前/之后和之前是否有空格,我希望该正则表达式能够检测到它。什么是正则表达式可以做到这一点?

【问题讨论】:

    标签: java regex string split


    【解决方案1】:

    换句话说,split 方法应该在 : 之前或之后查找零个或多个空格。

    Key: value
       ^^
    Key :value
       ^^
    Key:value
       ^
    Key : value
       ^^^
    

    在这种情况下,split("\\s*:\\s*") 应该可以解决问题。

    解释:

    • \\s 代表任何空格
    • * 表示之前描述的元素出现一次或多次
    • \\s* 表示零个或多个空格。

    另一方面,您可能还希望找到整个 key:value 对并将匹配 keyvalue 的部分放在不同的组中(您甚至可以使用 (?<groupName>regex) 随意命名组)。在这种情况下,您可以使用

    Pattern p = Pattern.compile("(?<key>\\w+)\\s*:\\s*(?<value>\\w+)");
    Matcher m = p.matcher(yourData);
    while(m.find()){
        System.out.println("key = " + m.group("key"));
        System.out.println("value = " + m.group("value"));
        System.out.println("--------");
    }
    

    【讨论】:

      【解决方案2】:

      如果你想使用String.split(),你可以使用这个:

      String input = "key : value";
      String[] s = input.split("\\s*:\\s*");
      String key = s[0];
      String value = s[1];
      

      这将在“:”处拆分字符串,但在“:”前面添加所有空格,以便您收到修剪后的字符串。

      解释:

      • \\s* 将匹配任何空格,默认情况下等于[ \\n\\r\\t]*
      • 两个 \\s* 之间的 : 表示您的 : 需要在那里

      请注意,如果您的输入行不包含您定义的键值格式,此解决方案将导致 ArrayIndexOutOfBoundsException

      如果您不确定该行是否真的包含键值字符串,可能是因为您想像往常一样在文件末尾有一个空行,您可以这样做:

      String input = "key : value";
      Matcher m = Pattern.compile("(\\S+)\\s*:\\s*(.+)").matcher(input);
      if (m.matches())
      {
          String key = m.group(1); // note that the count starts by 1 here
          String value = m.group(2);
      }
      

      解释:

      • \\S+ 匹配任何非空格字符串 - 如果它包含空格,则正则表达式的下一部分将与此表达式匹配。请注意,它周围的 () 标记,以便您可以通过 m.group() 获取它的值。
      • \\s* 将匹配任何空格,默认情况下等于[ \\n\\r\\t]*
      • 两个 \\s* 之间的 : 表示您的 : 需要在那里
      • 最后一组 .+ 将匹配任何字符串,包括空格等。

      【讨论】:

        【解决方案3】:

        您可以使用拆分方法,但可以将分隔符传递为“:”

        这会在看到':'时拆分字符串,然后您可以修剪值以获取键和值。

        String s = "   keys : value   ";
        String keyValuePairs[] = s.split(":");
        String key = keyValuePairs[0].trim();
        String value = keyValuePairs[1].trim();
        

        你也可以使用正则表达式来简化它。

        String keyValuePairs[] = s.trim().split("[ ]*:[ ]*");
        

        s.trim() 将删除字符串前后的空格(如果你有它的话),所以 sting 将变成“keys : value”和

        [ ]*:[ ]* 
        

        用正则表达式分割字符串,说空格(一个或多个):空格(一个或多个)作为分隔符。

        【讨论】:

          【解决方案4】:

          对于纯正则表达式解决方案,您可以使用以下模式(注意开头的空格):

           ?: ?
          

          http://regexr.com/39evh

          【讨论】:

          • 你为什么使用'?'代替 '*'?您只想匹配零个或一个“ ”吗?
          • 这真的取决于问题的细节 - 如果可以存在多个空格,则使用 *。
          • 但是 '*' 将匹配与 '?' 匹配的所有内容,所以我看不出有任何理由使用 '?'在这种情况下
          【解决方案5】:
           String[] tokensVal = str.split(":");
           String key = tokensVal[0].trim();
           String value = tokensVal[1].trim();
          

          【讨论】:

          • 这不会编译,不能重新定义局部变量key
          • 但 OP 无法从未记录和不可编译的(在 Pshemo 编辑您的答案之前)代码中学习
          猜你喜欢
          • 1970-01-01
          • 2022-10-07
          • 1970-01-01
          • 1970-01-01
          • 2018-09-08
          • 1970-01-01
          • 1970-01-01
          • 2017-03-21
          • 1970-01-01
          相关资源
          最近更新 更多