【问题标题】:Regular expression to split key=value正则表达式拆分键=值
【发布时间】:2013-04-19 07:58:29
【问题描述】:

我有一个这样的字符串:

KEY1=Value1, KE_Y2=[V@LUE2A, Value2B], Key3=, KEY4=V-AL.UE4, KEY5={Value5}

我需要拆分它以获得带有键值对的 Map。 [] 中的值应作为单个值传递(KE_Y2 是键,[V@LUE2A, Value2B] 是值)。

我应该使用什么正则表达式来正确拆分它?

【问题讨论】:

  • 您最好为此编写一个适当的解析器。如果处理得当,它将比正则表达式更健壮且更易于维护。
  • 你想如何存储键/值?即你想将它们都存储为字符串吗?我同意@TillHelgeHelwig,它也更灵活,因为您可以在解析时添加一些“动作”。
  • 是的。我需要把它们放在 Map.
  • @Sharpie,TillHelgeHelwig,要编写解析器,我仍然需要一个正则表达式来获取后跟逗号和空格符号的值。是不是走错路了?
  • 你能改变分隔符吗?如果您在每个值的末尾都有一个行尾,这将是一个经典的属性文件,可以作为经典的 Java 属性对象加载

标签: java regex string split


【解决方案1】:

第一次拆分有一个神奇的正则表达式:

String[] pairs = input.split(", *(?![^\\[\\]]*\\])");

然后用简单的“=”分割每个键/值:

for (String pair : pairs) {
    String[] parts = pair.split("=");
    String key = parts[0];
    String value = parts[1];
}

把它们放在一起:

Map<String, String> map = new HashMap<String, String>();
for (String pair : input.split(", *(?![^\\[\\]]*\\])")) {
    String[] parts = pair.split("=");
    map.put(parts[0], parts[1]);
}

瞧!


魔术正则表达式的解释:

正则表达式表示“逗号后跟任意数量的空格(因此键名没有前导空格),但前提是遇到的下一个括号不是右括号”

【讨论】:

  • 我花了 1.5 天时间尝试编写正确的正则表达式。但是你在几分钟内就做到了。你是巫师吗?非常感谢!!!
  • 没问题。一个巫师?好吧,我想无论如何我都在变得更好:)顺便说一句,请参阅最终要使用的代码的编辑答案-几行代码就干净整洁了。
  • 漂亮,它“像”我的回答,除了使用魔法来防止拆分值。好工作! +1
  • 这是捷克魔法。 (虽然到目前为止我还没有见过捷克人:P)
【解决方案2】:

这个怎么样:

Map<String, String> map = new HashMap<String, String>();
Pattern regex = Pattern.compile(
    "(\\w+)        # Match an alphanumeric identifier, capture in group 1\n" +
    "=             # Match =                                             \n" +
    "(             # Match and capture in group 2:                       \n" +
    " (?:          # Either...                                           \n" +
    "  \\[         #  a [                                                \n" +
    "  [^\\[\\]]*  #  followed by any number of characters except [ or ] \n" +
    "  \\]         #  followed by a ]                                    \n" +
    " |            # or...                                               \n" +
    "  [^\\[\\],]* #  any number of characters except commas, [ or ]     \n" +
    " )            # End of alternation                                  \n" +
    ")             # End of capturing group", 
    Pattern.COMMENTS);
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    map.put(regexMatcher.group(1), regexMatcher.group(2));
} 

【讨论】:

    【解决方案3】:

    从@achintya-jha 的回答开始。当你拆分一个字符串时,它会给你一个数组(或类似它的东西),所以你可以遍历这对键/值,然后你进行第二次拆分,这应该给你另一个大小为 2 的数组;然后,您将第一个元素用作键,将第二个元素用作值。

    编辑:

    我没有在 JAVA 中找到我的意思的有用链接(请参阅问题中的 cmets),(尽管有很多用于 C/C++ 的链接)所以我写了它:

    Map<String, String> map = new HashMap<String, String>();
    String str = "KEY1=Value1, KE_Y2=[V@LUE2A, Value2B]], Key3=, KEY4=V-AL.UE4, KEY5={Value5}";     
    
    
    final String openBrackets =  "({[<";
    final String closeBrackets = ")}]>";
    
    String buffer = "";
    int state = 0;
    int i = 0;      
    Stack<Integer> stack = new Stack<Integer>(); //For the brackets
    
    String key = "";
    
    
    while(  i < str.length() ) {
    
        char c = str.charAt(i);
    
    
        //Skip any whitespace
        if( " \t\n\r".indexOf(c) > -1 ) {
            ++i;
            continue;
        }
    
    
        switch(state) {
    
        //Reading Key
        case 0:
            if( c != '=' ) {
                buffer += c;
            } else {
                //Go read a value.
                key = buffer;
                state = 1;
                buffer = "";
            }
            ++i;
            break;
    
        //Reading value
        case 1:
    
            //Opening bracket
            int pos = openBrackets.indexOf(c);
            if( pos != -1 ) {
                stack.push(pos);
                ++i;
                break;
            }
    
            //Closing bracket
            pos = closeBrackets.indexOf(c);
            if( pos != -1 ) {
    
                if( stack.size() == 0 ) {
                    throw new RuntimeException("Syntax error: Unmatched closing bracket '" + c + "'" );
                }
    
                int pos2 = stack.pop();
                if( pos != pos2 ) {
                    throw new RuntimeException("Syntax error: Unmatched closing bracket, expected a '"
                            + closeBrackets.charAt(pos2) + "' got '" + c );             
                }
                ++i;
                break;
            }
    
            //Handling separators 
            if( c == ',' ) {
                if( stack.size() == 0 ) {
                    //Put the pair in the map.
                    map.put(key, buffer);
    
                    //Go read a new Key.
                    state = 0;
                    buffer = "";
                    ++i;
                    break;
                }                       
            }
    
            //else
                buffer += c;
                ++i;
    
    
            } //switch
    } //while
    

    【讨论】:

    • 注意:这样写,它也会删除任何空白。
    【解决方案4】:
    1. 用 String.split(","); 分割给定的字符串
    2. 现在用 String.split("="); 分割数组的每个元素;

    【讨论】:

    • 以及如何处理[]中的,,这应该是值的一部分?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 2013-08-11
    • 2021-12-04
    • 1970-01-01
    相关资源
    最近更新 更多