【问题标题】:Java RegEx for parsing the quoted arguments用于解析引用参数的 Java RegEx
【发布时间】:2014-06-07 05:11:40
【问题描述】:

以下场景需要 Java 正则表达式模式:

案例 1:

输入字符串:

"a"

匹配:

a

案例 2:

输入字符串:

"a b"

匹配:

a b

案例 3:

输入字符串:

"aA Bb" cCc 123 4 5 6 7xy "\"z9" "\"z9$^"

匹配:

aA Bb
cCc
123
4
5
6
7xy
"z9
"z9$^

案例 4:

输入字符串:

"a b c

匹配:

None - since the quotes are unbalanced, hence pattern match fails.

案例 5:

输入字符串:

"a b" "c

匹配:

None - since the quotes are unbalanced, hence pattern match fails.

案例 6:

输入字符串:

"a b" p q r "x y z"

匹配:

a b
p 
q 
r
x y z

案例 7:

输入字符串:

"a b" p q r "x y \"z\""

匹配:

a b
p 
q
r
x y "z"

案例 8:

输入字符串:

"a b" p q r "x \"y \"z\""

匹配:

a b
p 
q 
r
x "y "z"

当然还有最简单的一个:

案例 9:

输入字符串:

a b

匹配:

a
b

尝试使用模式,但似乎与上述所有情况都不匹配。

public List<String> parseArgs(String argStr) {
    List<String> params = new ArrayList<String>();
    String pattern = "\\s*(\"[^\"]+\"|[^\\s\"]+)";
    Pattern quotedParamPattern = Pattern.compile(pattern);
    Matcher matcher = quotedParamPattern.matcher(argStr);
    while (matcher.find()) {
        String param = matcher.group();
            System.out.println(param);
            params.add(param);
    }
    return params;
}

public void test(String argStr) {
    String[] testStrings = new String[]{"a", "a b", "a b \"c\"", "a b \"c"};
    for(String s: testStrings){
        parseArgs(s);
    }
}

【问题讨论】:

  • 它可以解决,但您需要付出一些努力来解决它。至少将所有示例输入字符串放在一个字符串数组 (String[]) 中,并将 Java 代码放在这里。
  • @anubhava 添加了 Java 代码和一些输入字符串。
  • 我猜你的实际字符串不仅仅是单个小写字母。它们是否需要包含大写字母、数字、特殊字符等?他们应该多长时间有限制吗?
  • @CAustin 可能有大写字母、数字、特殊字符等,但没有限制。
  • 我不确定你想要什么,但我敢肯定答案是在你到达这个之前。

标签: java regex arguments pattern-matching command-line-arguments


【解决方案1】:

试试这个:

("\S+?(?: \S+?)*"|\S+?)

查看实际操作:http://regex101.com/r/fA5hN0

只需运行全局匹配并返回 \1。返回的每个捕获组都应该包含您想要的内容。

【讨论】:

  • 是否有可用的 Java 正则表达式字符串,因为上述模式需要转义斜杠和引号,即使转义,它似乎也不适用于所有情况。尝试了这个输入字符串:"a b" p q r "x y \"z\""
【解决方案2】:

为了让您开始,您可以使用这个基于 Java 正则表达式的代码:

public List<String> parseArgs(String argStr, Pattern validPattern, Pattern parsePattern) {
    List<String> params = null;
    if (validPattern.matcher(argStr).matches()) {
        params = new ArrayList<String>();
        Matcher matcher = parsePattern.matcher(argStr); 
        while (matcher.find())
            params.add( matcher.group(1) != null ? matcher.group(1) : matcher.group(2));
    }
    return params;
}

public void parseIt() {
    Pattern validatePattern = Pattern.compile("^(?=(?:(?:[^\"]*\"){2})*[^\"]*$).*$");
    Pattern parsingPattern = Pattern.compile("\"([^\"]*)\"|(\\w+)");

    String[] testStrings = new String[]{
             "a", "a b", "a b \"c\"", "a b \"c", "\"a b\" p q r \"x y z\""};
    for(String s: testStrings) {
        List<String> parsedList = parseArgs(s, validatePattern, parsingPattern);
        System.out.printf("input: %-30s :: parsed: %s%n", s, parsedList);
    }
}

输出:

input: a                              :: parsed: [a]
input: a b                            :: parsed: [a, b]
input: a b "c"                        :: parsed: [a, b, c]
input: a b "c                         :: parsed: null
input: "a b" p q r "x y z"            :: parsed: [a b, p, q, r, x y z]

PS:虽然我注意到您在最近的编辑中也添加了嵌套引号,但需要为此增强此答案。

【讨论】:

  • 这似乎适用于大多数情况。但我正在尝试提取其中也有转义引号的字符串。试过这个: "aA Bb" cCc 123 4 5 6 7xy "\"z9" "\"z9$^" 这应该给我 "z9 作为第 8 个参数和 "z9$^ 作为第 9 个参数。谢谢。
  • 是的,我记下了它,因为我之前没有注意到您问题中的转义/嵌套引号。
  • 什么正则表达式可以匹配以上所有情况?
  • 其实逃避是没有尽头的。甚至反斜杠也可以转义。你是如何得到这个输入的?
  • 是的,没错。这就是它应该为我正在构建的应用程序工作的方式。即使这是有效的 "aA Bb" cCc 123 4 5 6 7xy "\"\\z9" "\"z9$^"。并且正在从标准输入读取字符串。
【解决方案3】:

我不知道用正则表达式解决的直接方法。

但是你可以用一些唯一的关键字替换内部转义序列,然后你可以用正则表达式匹配你的字符串。

String[] testStrings = new String[]{
         "a", "a b", "a b \"c\"", "a b \"c", "\"a b\" p q r \"x y z\""};
Pattern parsingPattern = Pattern.compile("(\".*?\")|( [^ ^\"]+)");
for(String s: testStrings) {
   s=s.replace("(?<!\\)\\"","@@@");
}
for(String s: testStrings) {
    List<String> params = null;
    int count = StringUtils.countMatches(s, "\"");
    if(count%2==0){
    params = new ArrayList<String>();
    Matcher matcher = parsePattern.matcher(s); 
    while (matcher.find())
        params.add( matcher.group(1) != null ? matcher.group(1) : matcher.group(2));
   }
}

一旦你得到匹配,你可以用实际的关键字替换你的唯一标识符..

我还没有测试过sn-p的代码,但我希望你能做一些小的调整来让它工作。

【讨论】:

  • 似乎是一个公平的解决方案。谢谢!
【解决方案4】:

编写了一个“CLIParser”类,它会给你结果。

//instantiate the CLIParser 

CLIParser parser = new CLIParser("\"a b\" p q r \"x y z\"");

//call the method getTokens which gives you the result.

ArrayList<String> resultTokens = parser.getTokens();


###################CLI Parser Class definition#################################

class CLIParser {
    private String cmdString;

    public CLIParser(String cmdString) {
        this.cmdString = cmdString;
    }

    public ArrayList<String> getTokens() throws Exception {
        ArrayList<String> finalTokens = new ArrayList<String>();
        ArrayList<StringBuffer> tokens = new ArrayList<StringBuffer>();
    char inArray[] = this.cmdString.toCharArray();
    StringBuffer token = new StringBuffer();
    int valid = checkIfTheStringIsValid(inArray);
    if (valid == -1) {
        for (int i = 0; i <= inArray.length; i++) {

            if (i != inArray.length) {
                if ((inArray[i] != ' ') && (inArray[i] != '"')) {
                    token.append(inArray[i]);
                }

                if ((inArray[i] == '"') && (inArray[i - 1] != '\\')) {
                    i = i + 1;
                    while (checkIfLastQuote(inArray, i)) {
                        token.append(inArray[i]);
                        i++;
                    }
                }
            }
            if (i == inArray.length) {
                tokens.add(token);
                token = new StringBuffer();
            } else if (inArray[i] == ' ' && inArray[i] != '"') {
                tokens.add(token);
                token = new StringBuffer();
            }
        }
    } else {
        throw new InvalidCommandException(
                "Invalid command. Couldn't identify sequence at position "
                        + valid);
    }
    for(StringBuffer tok:tokens){
        finalTokens.add(tok.toString());
    }
    return finalTokens;
}

private static int checkIfTheStringIsValid(char[] inArray) {
    Stack myStack = new Stack<Character>();
    int pos = 0;
    for (int i = 0; i < inArray.length; i++) {
        if (inArray[i] == '"' && inArray[i - 1] != '\\') {
            pos = i;
            if (myStack.isEmpty())
                myStack.push(inArray[i]);
            else
                myStack.pop();
        }
    }
    if (myStack.isEmpty())
        return -1;
    else
        return pos;
}

private static boolean checkIfLastQuote(char inArray[], int i) {
    if (inArray[i] == '"') {
        if (inArray[i - 1] == '\\') {
            return true;
        } else
            return false;
    } else
        return true;
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 2010-09-25
    • 2019-04-28
    • 2019-04-15
    • 2010-11-29
    • 2012-09-08
    相关资源
    最近更新 更多