如何解析一个双引号包含转义双引号的字符串

4
我需要解析来自流的行,看起来像这样:command "string1" "string2" 字符串可以包含空格和转义的双引号。我需要将其拆分,以便将command,string1和string2作为数组元素获取。我认为使用正则表达式匹配"但不是\".split("(?<!\\\\)\""))可以完成任务,但我听说这不是一个好主意。
在Java中有更好的方法吗?

6
这不是免费的代码编写服务。试一试,如果你无法让它工作,请发布你所做的和出现了什么问题,我们会尝试帮助你。 - Robert Columbia
老实说,只需在空格上进行分割,然后单独解析命令参数即可。你不必为此使用正则表达式。 - Dici
@Dici 我无法根据空格进行拆分,因为参数可能包含空格。 - user1902247
@RobertColumbia 我不是在要求代码,我是在问是否有更好的方法来做这件事。 - user1902247
@user1902247 更新了答案,由rici指导。 - Dici
1个回答

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);
        }
    }
}

输出:

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

正则表达式有些复杂,因此值得解释一下:

  • [^\\\\\"] 匹配除了反斜杠和双引号以外的所有字符
  • \\\\. 匹配反斜杠后紧跟着任何一个字符(包括双引号),即转义字符
  • (?:[^\\\\\"]|\\\\.)* 匹配包含转义或非转义字符的任何序列,但不捕获该组(由于(?:)
  • "\"((?:[^\\\\\"]|\\\\.)*)\"匹配任何这样的序列,用双引号括起来并捕获括号内的内容
  • ([^\\s\"]+) 匹配任何非空的非空格字符序列,并将其捕获在一个组中

谢谢,很抱歉打扰您,但是相比于 str.split("(?<!\\\\)\""),这种方法有什么优势呢? - user1902247
@dici:我没有进行过dv,但是谁曾经这样做过,可能是因为它不起作用。尝试在像OP中具有两个不同双引号子字符串的输入上运行它。而且它也不能处理转义引号,虽然只有在解决第一个问题时才会有影响。 - rici
@rici 取决于您期望的输出。它符合我的期望,但不符合您的期望,也不一定符合 OP 的期望。由于 OP 没有明确说明要求,因此我很好奇您是如何理解这些要求的。 - Dici
1
我理解要求是将 command "string1" "string2" 分成三部分。这似乎非常明确。据我所知你的程序只会把它分成两部分。(如果我错了,请随便指出我的错误)。还有一个期望,即去掉引号,但这并不明确。 - rici
1
如果你尝试使用回顾,很可能会出错,因为你需要区分 \"(转义引号)、\\\"(转义反斜杠后跟一个结束字符串的引号)、\\\"(转义反斜杠后跟转义引号)等。犯这些错误是非常常见的 bug。我的解决方案实际上是有效的;我只是不确定我是否正确地转义了 Java 字符串和正则表达式中的所有内容。 - rici
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接