I need to parse strings intended for cross-spawn
From the following strings:
cmd foo bar
cmd "foo bar" --baz boom
cmd "baz \"boo\" bam"
cmd "foo 'bar bud' jim" jam
FOO=bar cmd baz
To an object:
{command: 'cmd', args: ['foo', 'bar']}
{command: 'cmd', args: ['foo bar', '--baz', 'boom']}
{command: 'cmd', args: ['baz "boo" bam']}
{command: 'cmd', args: ['foo \'bar bud\' jim', 'jam']}
{command: 'cmd', args: ['baz'], env: {FOO: 'bar'}}
I'm thinking a regex would be possible, but I'd love to avoid writing something custom. Anyone know of anything existing that could do this?
The question and answers are still valuable, but for my specific use-case I no longer need to do this. I'll use spawn-command
instead (more accurately, I'll use spawn-command-with-kill
) which doesn't require the command
and args
to be separate. This will make life much easier for me. Thanks!
A regular expression could match your command line...
^\s*(?:((?:(?:"(?:\\.|[^"])*")|(?:'[^']*')|(?:\\.)|\S)+)\s*)$
... but you wouldn't be able to extract individual words. Instead, you need to match the next word and accumulate it into a command line.
function parse_cmdline(cmdline) {
var re_next_arg = /^\s*((?:(?:"(?:\\.|[^"])*")|(?:'[^']*')|\\.|\S)+)\s*(.*)$/;
var next_arg = ['', '', cmdline];
var args = [];
while (next_arg = re_next_arg.exec(next_arg[2])) {
var quoted_arg = next_arg[1];
var unquoted_arg = "";
while (quoted_arg.length > 0) {
if (/^"/.test(quoted_arg)) {
var quoted_part = /^"((?:\\.|[^"])*)"(.*)$/.exec(quoted_arg);
unquoted_arg += quoted_part[1].replace(/\\(.)/g, "$1");
quoted_arg = quoted_part[2];
} else if (/^'/.test(quoted_arg)) {
var quoted_part = /^'([^']*)'(.*)$/.exec(quoted_arg);
unquoted_arg += quoted_part[1];
quoted_arg = quoted_part[2];
} else if (/^\\/.test(quoted_arg)) {
unquoted_arg += quoted_arg[1];
quoted_arg = quoted_arg.substring(2);
} else {
unquoted_arg += quoted_arg[0];
quoted_arg = quoted_arg.substring(1);
}
}
args[args.length] = unquoted_arg;
}
return args;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With