有没有一种简单的方法可以将此文本解析为Map

时间:2012-01-15 03:25:11

标签: java regex algorithm parsing groovy

我收到服务的回复,如下所示。如何将其解析为Map?我首先考虑在空白处拆分,但它不起作用,因为值可能包含空格,例如在下面的回复中查看 SA 键的值。

我想到的一个选项是在空格中分割提供前一个字符是双引号。不知道怎么写这个正则表达式。

TX =“0000000000108000001830001”FI =“”OS =“8”CI =“QU01SF1S2032”AW =“SSS”SA =“1525 Windward Concourse”

3 个答案:

答案 0 :(得分:4)

解析引号。您甚至可以使用正则表达式来查找每个键/值对,假设每个值都在引号中。我唯一的问题是,如果值包含嵌入式引号,那么规则是什么? (他们是否使用“\”或类似物进行了逃生?无论如何,目前这还没有在下面说明......)

例如:

(\w+)="([^"]*)"

这甚至可以为您提供可分别用于提供密钥和值的组#1和#2。

使用Java的Matcher.find()方法循环运行,直到找到所有对。

示例代码:

String input = "TX=\"0000000000108000001830001\" FI=\"\" OS=\"8\" CI=\"QU01SF1S2032\" AW=\"SSS\" SA=\"1525 Windward Concourse\"";

Pattern p = Pattern.compile("\\s*(\\w+)=\"([^\"]*)\"\\s*");

Matcher m = p.matcher(input);
while(m.find()){
    System.out.println(m.group(1));
    System.out.println(m.group(2));
}

输出:

TX
0000000000108000001830001
FI

OS
8
CI
QU01SF1S2032
AW
SSS
SA
1525 Windward Concourse

答案 1 :(得分:3)

根据文本的外观,它似乎可能是一个XML。是这样,还是该文本是服务的原始响应?如果它是XML,您可以使用Groovy的XmlSlurper轻松解析它:

def input = '<root TX="0000000000108000001830001" FI="" OS="8" CI="QU01SF1S2032" AW="SSS" SA="1525 Windward Concourse"></root>'
def xml = new XmlSlurper().parseText(input)

def map = xml.attributes()

map变量为[CI:QU01SF1S2032, AW:SSS, TX:0000000000108000001830001, OS:8, FI:, SA:1525 Windward Concourse]

如果它不是XML,您可以关注ziesemer's answer并使用正则表达式。他生成Map的答案的groovier版本将是:

def input = 'TX="0000000000108000001830001" FI="" OS="8" CI="QU01SF1S2032" AW="SSS" SA="1525 Windward Concourse"'
def match = input =~ /(\w+)="([^"]*)"/

def map = [:]
match.each {
    map[it[1]] = it[2]
}

map的结果与以前相同。

答案 2 :(得分:2)

StreamTokenizer速度很快,但我没有使用quoteChar()功能。可以找到示例hereherehere

控制台:

TX=0000000000108000001830001
FI=
OS=8
CI=QU01SF1S2032
AW=SSS
SA=1525 Windward Concourse
Count: 6
0.623 ms

代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;

/** @see https://stackoverflow.com/questions/8867325 */
public class TokenizerTest {

    private static final String s = ""
        + "TX=\"0000000000108000001830001\" FI=\"\" OS=\"8\" "
        + "CI=\"QU01SF1S2032\" AW=\"SSS\" SA=\"1525 Windward Concourse\"";
    private static final char equal = '=';
    private static final char quote = '"';
    private static StreamTokenizer tokens = new StreamTokenizer(
        new BufferedReader(new StringReader(s)));

    public static void main(String[] args) {
        long start = System.nanoTime();
        tokenize();
        long stop = System.nanoTime();
        System.out.println((stop - start) / 1000000d + " ms");
    }

    private static void tokenize() {
        tokens.ordinaryChar(equal);
        tokens.quoteChar(quote);
        try {
            int count = 0;
            int token = tokens.nextToken();
            while (token != StreamTokenizer.TT_EOF) {
                if (token == StreamTokenizer.TT_WORD) {
                    System.out.print(tokens.sval);
                    count++;
                }
                if (token == equal) {
                    System.out.print(equal);
                }
                if (token == quote) {
                    System.out.println(tokens.sval);
                }
                token = tokens.nextToken();
            }
            System.out.println("Count: " + count);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}