Java 提取键/值对,值可以跨行

Java 提取键/值对,值可以跨行,java,Java,输入文件: key1=1 key2=start(a b c= d)end key3=d=e=f somekey=start(123)end morekey=start(1 2)end key=jj 输出 key1 -> 1 key2 -> a b c= d key3 -> d=e=f somekey -> 123 morekey -> 1 2 key

输入文件:

key1=1
key2=start(a
b
c=
d)end
key3=d=e=f
somekey=start(123)end
morekey=start(1
2)end
key=jj
输出

key1    -> 1
key2    -> a
           b
           c=
           d
key3    -> d=e=f
somekey -> 123
morekey -> 1
           2
key     -> jj
请求:在java中尝试。无法使用java.util.Properties,正则表达式可以,但不是首选,首选StringUtils.substringBetween,但正则表达式可以。如何遍历多行并保留换行符。 以下内容显然不适用于多行。我们打算尝试正则表达式,但前提是不可能使用更优雅的方法

    String[] str = line.split("=", 2);
    StringUtils.substringBetween(line,startString,endString)); 

解决这个问题的一种方法是编写自己的解析器。例如:

public static final String START = "start(";
public static final String END = ")end";

// ...

Scanner scanner = new Scanner(
        "key1=1\n" +
        "key2=start(a\n" +
        "b\n" +
        "c=\n" +
        "d)end\n" +
        "key3=d=e=f\n" +
        "somekey=start(123)end\n" +
        "morekey=start(1\n" +
        "2)end\n" +
        "key=jj");

Map<String, String> map = new HashMap<>();
while (scanner.hasNext()) {
    String line = scanner.nextLine();
    int eq = line.indexOf('=');
    String key = line.substring(0, eq);
    String value = line.substring(eq + 1);
    if (value.startsWith(START)) {
        StringBuilder sb = new StringBuilder(value.substring(START.length()));
        while (!value.endsWith(END)) {
            value = scanner.nextLine();
            sb.append('\n').append(value);
        }
        value = sb.substring(0, sb.length() - END.length());
    }
    map.put(key, value);
}

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.printf("%s -> %s\n", entry.getKey(), entry.getValue());
}
公共静态最终字符串START=“START(”;
公共静态最终字符串END=“)END”;
// ...
扫描仪=新扫描仪(
“key1=1\n”+
“key2=开始(a\n”+
“b\n”+
“c=\n”+
“d)结束\n”+
“key3=d=e=f\n”+
“somekey=start(123)end\n”+
“morekey=start(1\n”+
“2)结束\n”+
“key=jj”);
Map Map=newhashmap();
while(scanner.hasNext()){
字符串行=scanner.nextLine();
int eq=line.indexOf('=');
字符串键=行。子字符串(0,eq);
字符串值=行。子字符串(等式+1);
if(值.startsWith(开始)){
StringBuilder sb=新的StringBuilder(value.substring(START.length());
而(!value.endsWith(END)){
值=scanner.nextLine();
sb.append('\n')。append(value);
}
value=sb.substring(0,sb.length()-END.length());
}
map.put(键、值);
}
对于(Map.Entry:Map.entrySet()){
System.out.printf(“%s->%s\n”,entry.getKey(),entry.getValue());
}

你的意思是这样的吗:

String str = "key1=1\n"
        + "key2=start(a\n"
        + "b\n"
        + "c=\n"
        + "d)end\n"
        + "key3=d=e=f\n"
        + "somekey=start(123)end\n"
        + "morekey=start(1\n"
        + "2)end\n"
        + "key=jj";
System.out.println(str.replaceAll("start\\(|\\)end", "")
        .replaceAll("(\\w{2})=", "$1\t-> ")
        .replaceAll("(\n\\w)", "\t$1"));

以下正则表达式可以找到所有键/值对:

(?ms)^(\w+)=(?:开始\(.*)结束\(.*))$

密钥将位于捕获组1中,值将位于捕获组2或3中

试验


当你做这样的事情时它叫什么:“(\\w{2})=”?我真的很想了解它,但不知道该怎么做。我把这个
”(\\w{2})=“
作为特例
c=
@elasfyksen为什么?因为有一个后跟=so的键来避免替换这个
c=
我使用了
“(\\w{2})=”
,所以它会用这个组替换每个=我用
(\\w{2}
表示它
$1
=/code>表示它
->\s
@elasfyksen?你明白了吗?我的意思是:这种技术叫什么。是正则表达式吗?PS:noob Hereah阅读了关于团体@EliasFyksen的文章
String input = "key1=1\r\n" +
               "key2=start(a\r\n" +
               "b\r\n" +
               "c=\r\n" +
               "d)end\r\n" +
               "key3=d=e=f\r\n" +
               "somekey=start(123)end\r\n" +
               "morekey=start(1\r\n" +
               "2)end\r\n" +
               "key=jj\r\n";

String regex = "(?ms)^(\\w+)=(?:start\\((.*?)\\)end|(.*?))$";

Map<String, String> map = new HashMap<>();
for (Matcher m = Pattern.compile(regex).matcher(input); m.find(); )
    map.put(m.group(1), (m.start(2) != -1 ? m.group(2) : m.group(3)));

for (Entry<String, String> e : map.entrySet())
    System.out.printf("%-7s -> %s%n", e.getKey(),
                      e.getValue().replaceAll("(\\R)", "$1           "));