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

use*_*247 4 java regex string parsing

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

在Java中有没有更好的方法来做到这一点?

Dic*_*ici 5

假设您想在适用时删除外部双引号(如果您不这样做,只需更改第一个捕获组以也包含引号),类似的事情应该可以解决问题:

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

输出:

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

正则表达式有点复杂,因此值得对其进行一些解释:

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