使用Java解析包含转义字符的字符串

时间:2009-05-10 12:20:56

标签: java regex

我想知道是否有人可以帮我弄清楚如何解析具有以下格式的字符串:

;field1-field2-fieldN;field1-field2-fieldN;

每条记录都以';'分隔并且记录中的每个字段由“ - ”分隔。复杂的是,各个字段可能包含转义的分隔符字符,如“\;”要么 ”-”。这导致我下面的简单解析代码失败。所以我想要做的是提出与分隔符匹配但与转义分隔符不匹配的正则表达式。 我的正则表达式知识并不是那么好,但我希望必须有一种方法可以将“([^ \;])”和“([;])”结合起来得到我需要的东西。

public static List<ParsedRecord> parse(String data) {
    List<ParsedRecord> parsedRecords = new List<ParsedRecord>();
    String[] records = data.split(";");
    for (String record : records) {
        String[] fields = data.split("-");
        parsedRecords.add(new parsedRecord(fields));
    }
    return parsedRecords;
}

非常感谢。

2 个答案:

答案 0 :(得分:7)

你可能最好在同一传球中进行失误和分裂。我知道在分离两个独立的功能方面感觉不对,但它避免了一些尴尬的角落情况(例如,想象“foo \; bar”,其中;遵循反斜杠但仍然是分隔符)。

这里有一些非常简单的代码来进行解析 - 它假设任何反斜杠基本上都意味着“将下一个字符视为普通输入”,但这就是全部。

import java.util.*;

public class Test
{
    public static void main(String[] args)
    {
        List<String> parsed = parse(args[0]);
        for (String x : parsed)
        {
            System.out.println(x);
        }
    }

    public static List<String> parse(String text)
    {
        List<String> ret = new ArrayList<String>();
        StringBuilder current = new StringBuilder();
        boolean escaping = false;

        for (int i=0; i < text.length(); i++)
        {
            char c = text.charAt(i);
            if (escaping)
            {
                current.append(c);
                escaping = false;
            }
            else
            {
                if (c == '\\')
                {
                    escaping = true;
                }
                else if (c == ';')
                {
                    ret.add(current.toString());
                    current = new StringBuilder();
                }
                else
                {
                    current.append(c);
                }
            }
        }
        if (escaping)
        {
            throw new IllegalArgumentException("Ended in escape sequence");
        }
        ret.add(current.toString());
        return ret;
    }
}

(请注意,这并不是将每个记录分成多个字段的业务,但您只需要更改您使用';'进行的操作,并对' - '做出反应 - 原则是相同的。 )

答案 1 :(得分:7)

您可以使用这样的分割来优化用于分割的正则表达式:

split("[^\\];")

要拆分任何“;”但如果之前有一个“\”,则不会。破折号也是如此:

split("[^\\]-")