Java 如何像字符串一样拆分命令行?

Java 如何像字符串一样拆分命令行?,java,regex,Java,Regex,基本上,我需要像这样拆分字符串 "one quoted argument" those are separate arguments "but not \"this one\"" 获取参数列表的结果 “一个引用的参数” 那些 是 分开 “但不是“这个” 这个正则表达式几乎可以完成这项工作,但问题是正则表达式总是(至少在java中)尝试匹配最长的字符串 因此,当我将正则表达式应用于以带引号的参数开头和结尾的字符串时,它将匹配整个字符串,并且不会为每个参数创建一个组 有没有办法调整这个正则表达

基本上,我需要像这样拆分字符串

"one quoted argument" those are separate arguments "but not \"this one\""
获取参数列表的结果

  • “一个引用的参数”
  • 那些
  • 分开
  • “但不是“这个”
这个正则表达式几乎可以完成这项工作,但问题是正则表达式总是(至少在java中)尝试匹配最长的字符串

因此,当我将正则表达式应用于以带引号的参数开头和结尾的字符串时,它将匹配整个字符串,并且不会为每个参数创建一个组

有没有办法调整这个正则表达式或处理它

注意:不要告诉我我可以使用
GetOpt
CommandLine.parse
或其他类似工具。
我关心的是纯java正则表达式(如果可能的话,但我对此表示怀疑…。

正则表达式总是(至少在java中)尝试匹配 尽可能长的字符串

嗯。。。没有

这由是否使用贪婪或非贪婪表达式控制。看见使用一个非贪婪的(通过添加问号)应该可以做到这一点。它叫


默认值为贪婪,但这并不意味着总是这样。

您可以使用非贪婪限定符
*?
使其工作:

"(\\"|[^"])*?"|[^ ]+
请参阅此链接以获取操作示例:

publicstaticstring[]parseCommand(stringcmd)
{
如果(cmd==null | | cmd.length()==0)
{
返回新字符串[]
{};
}
cmd=cmd.trim();
字符串regExp=“\”(\\\“\[^\”])*?\“\[^]+”;
Pattern=Pattern.compile(regExp,Pattern.MULTILINE | Pattern.CASE_不区分大小写);
Matcher-Matcher=pattern.Matcher(cmd);
Listmatches=newarraylist();
while(matcher.find()){
matches.add(matcher.group());
}
String[]parsedCommand=matches.toArray(新字符串[]{});
返回解析的命令;
}
我想出了这个(感谢Alex给了我一个好的起点:)

/**
*能够处理复杂命令行引用和
*逃跑。这可以正确识别:
*
    *
  • “双引号字符串” *
  • “单引号字符串” *
  • 带引号字符串中的“转义”引号 *
  • C:\path\like\this或“C:\path like\this” *
  • --arguments=like_this或--args=like this或'--args=like this'或 *--args=“像这样”或--args=“像这样” *
  • quoted\whitespaces\\t(空格和制表符) *
  • 可能更多:) *
*/ 私有静态最终模式cliCracker=模式 .编译( “[^\\s]*\”(\\+“[^\”)*?\“[^\\s]*”(\\\+'.[^'])*?”(\\\+'.[^'])*?”(\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\, 模式(多行);
我认为正则表达式是不可能的,但我可能错了。使用
*?
这样正则表达式就不会贪婪了
“(\\“\\\\\[^”])*?“\\[^]+
符合您的需要。@Alex如果您回答了这个问题,我将投票决定它应该如何处理
“一个带引号的参数”这些是单独的参数,“而不是\\\\\”
?A.R.S.是正确的,您不能使用Java(兼容Perl 5)正则表达式来解析全套可能的命令行。原因是您所指的转义可以递归嵌套。您可能需要一个解析器,或者需要一个不同的正则表达式引擎(请参阅更新版本的Perl中的正则表达式系统,它可以做到这一点)。建议:将
[^]+
替换为
[^\s]+
,这样它就可以处理制表符或其他空白字符,并将使用它进行测试。FWIW这里是-行337的实现-请参阅可能将NPE抛出null?此外,您还应该根据-缓存模式,并且
cmd.length()==0
将由regex@Igor这是解决这个问题的一个很好的开端,但对最后一个案例不起作用。
public static String[] parseCommand( String cmd )
{
    if( cmd == null || cmd.length() == 0 )
    {
        return new String[]
        {};
    }

    cmd = cmd.trim();
    String regExp = "\"(\\\"|[^\"])*?\"|[^ ]+";
    Pattern pattern = Pattern.compile( regExp, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE );
    Matcher matcher = pattern.matcher( cmd );
    List< String > matches = new ArrayList< String >();
    while( matcher.find() ) {
        matches.add( matcher.group() );
    }
    String[] parsedCommand = matches.toArray(new String[] {});
    return parsedCommand;
}
/**
 * Pattern that is capable of dealing with complex command line quoting and
 * escaping. This can recognize correctly:
 * <ul>
 * <li>"double quoted strings"
 * <li>'single quoted strings'
 * <li>"escaped \"quotes within\" quoted string"
 * <li>C:\paths\like\this or "C:\path like\this"
 * <li>--arguments=like_this or "--args=like this" or '--args=like this' or
 * --args="like this" or --args='like this'
 * <li>quoted\ whitespaces\\t (spaces & tabs)
 * <li>and probably more :)
 * </ul>
 */
private static final Pattern cliCracker = Pattern
    .compile(
       "[^\\s]*\"(\\\\+\"|[^\"])*?\"|[^\\s]*'(\\\\+'|[^'])*?'|(\\\\\\s|[^\\s])+",
       Pattern.MULTILINE);