如何解析可以包含转义双引号的双引号分隔字符串

时间:2016-08-07 00:00:06

标签: java regex string parsing

我需要解析流中看起来像这样的行:command "string1" "string2"字符串可以包含空格和转义双引号。我需要拆分它,以便我得到命令,string1和string2作为数组元素。我认为split()与正则表达式匹配"而不是\".split("(?<!\\\\)\""))可以完成这项工作,但我听说这不是一个好主意。

在Java中有没有更好的方法呢?

1 个答案:

答案 0 :(得分:3)

这样的事情可以解决这个问题,假设你想在适用的时候删除外部双引号(如果你不这样做,只需要改变第一个捕获组也包括引号):

public class Demo {
    private static final Pattern WORD = 
        Pattern.compile("\"((?:[^\\\\\"]|\\\\.)*)\"|([^\\s\"]+)");

    public static void main(String[] args) {
        String  cmd = 
           "command "                                  +
           "\"string with blanks\" "                   +
           "\"anotherStringBetweenQuotes\" "           +
           "\"a string with \\\"escaped\\\" quotes\" " + 
           "stringWithoutBlanks";

        Matcher matcher = WORD.matcher(cmd);
        while (matcher.find()) {
            String capturedGroup = matcher.group(1) != null ? matcher.group(1) : matcher.group(2);
            System.out.println("Matched: " + capturedGroup);
        }
    }
}

输出:

Matched: command
Matched: string with blanks
Matched: anotherStringBetweenQuotes
Matched: a string with \"escaped\" quotes
Matched: stringWithoutBlanks

正则表达式有点复杂,所以值得一点解释:

  • [^\\\\\"]匹配除反斜杠或双引号之外的所有内容
  • \\\\.匹配反斜杠后跟任何字符(包括双引号),即转义字符
  • (?:[^\\\\\"]|\\\\.)*匹配任何已转义或未转义的字符序列,但未捕获该组(因为(?:)
  • "\"((?:[^\\\\\"]|\\\\.)*)\"匹配包含在双引号中的任何此类序列并捕获引号内部
  • ([^\\s\"]+)匹配任何非空的非空字符序列,并将其捕获到一个组中