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\""
获取参数列表的结果
- “一个引用的参数”
- 那些
- 是
- 分开
- “但不是“这个”
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);