Skip to content

Instantly share code, notes, and snippets.

@amake
Last active December 16, 2015 16:49
Show Gist options
  • Save amake/5465701 to your computer and use it in GitHub Desktop.
Save amake/5465701 to your computer and use it in GitHub Desktop.
A function for correctly parsing CLI commands with quotes and escape characters, on Windows, Linux, and OS X.
/**************************************************************************
Public Domain
To the extent possible under law, Aaron Madlon-Kay has waived all
copyright and related or neighboring rights to this work.
This work is published from: Japan
**************************************************************************/
package org.amk;
import java.util.ArrayList;
import java.util.List;
public class ParseCLI {
/**
* Parse a command line string into arguments, interpreting
* double and single quotes as Bash does.
*
* Use '\' to escape whitespace (outside of quotes only)
* and to escape double quotes (inside double quotes only).
*
* This is suitable for parsing arguments to be passed to
* {@link Runtime#exec(String[])}, on Windows, Linux, and
* OS X.
*
* @param cmd Command string
* @return Array of arguments
*/
public static String[] parseCLICommand(String cmd) {
cmd = cmd.trim();
if (cmd.length() == 0) return new String[] { "" };
StringBuilder arg = new StringBuilder();
List<String> result = new ArrayList<String>();
final char noQuote = '\0';
char currentQuote = noQuote;
for (int i = 0; i < cmd.length(); i++) {
char c = cmd.charAt(i);
if (c == currentQuote) {
currentQuote = noQuote;
} else if (c == '"' && currentQuote == noQuote) {
currentQuote = '"';
} else if (c == '\'' && currentQuote == noQuote) {
currentQuote = '\'';
} else if (c == '\\' && i + 1 < cmd.length()) {
char next = cmd.charAt(i + 1);
if ((currentQuote == noQuote && Character.isWhitespace(next))
|| (currentQuote == '"' && next == '"')) {
arg.append(next);
i++;
} else {
arg.append(c);
}
} else {
if (Character.isWhitespace(c) && currentQuote == noQuote) {
if (arg.length() > 0) {
result.add(arg.toString());
arg = new StringBuilder();
} else {
// Discard
}
} else {
arg.append(c);
}
}
}
// Catch last arg
if (arg.length() > 0) {
result.add(arg.toString());
}
return result.toArray(new String[0]);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment