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

5 java regex


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

;field1-field2-fieldN;field1-field2-fieldN;
Run Code Online (Sandbox Code Playgroud)

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

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;
}
Run Code Online (Sandbox Code Playgroud)

首先十分感谢.

Jon*_*eet 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Fab*_*eeg 7

您可以使用这样的方式优化与split一起使用的正则表达式:

split("[^\\];")
Run Code Online (Sandbox Code Playgroud)

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

split("[^\\]-")
Run Code Online (Sandbox Code Playgroud)

  • 这不太正确......上面定义的正则表达式也将在分隔符之前的字符被剥离.所以"你好,世界"变成了[地狱,世界].更好的方法是在正则表达式中使用负面外观机制:http://stackoverflow.com/questions/820172/how-to-split-a-comma-separated-string-while-ignoring-escaped-commas (2认同)