Is there a way in C to parse a piece of text and obtain values for argv and argc, as if the text had been passed to an application on the command line?
This doesn\'
My project requires breaking a string into argc and argv.
Found a pretty excellent code of Torek. But it alters the input buffer so I made some modifications to fit my needs.
I just put a little bit more to handle quote mixing when input in the command line so the behavior is more (not completely) like Linux Shell.
Note: This function doesn't edit the original string, so you can reuse the input buffer (error report,etc).
void remove_quote(char* input){
//Implementing yourself to remove quotes so it would be completely like Linux shell
}
size_t cmd_param_split(char *buffer, char *argv[], size_t argv_max_size)
{
char *p, *start_of_word;
int c, i;
enum states { DULL=0, IN_WORD, IN_STRING, QUOTE_DOUBLE,QUOTE_SINGLE } state = DULL;
size_t argc = 0;
int quote = 0;
for (p = buffer; argc < argv_max_size && *p != '\0'; p++) {
c = (unsigned char) *p;
printf("processing %c, state = %d\n", c,state);
switch (state) {
case DULL:
if (isspace(c)) {
continue;
}
if (c == '"' ||c == '\'') {
quote = c;
state = IN_STRING;
start_of_word = p + 1;
continue;
}
state = IN_WORD;
start_of_word = p;
continue;
case IN_STRING:
if (c == '"' || c == '\'') {
if (c!=quote)
continue;
else
quote = 0;
strncpy(argv[argc],start_of_word, p - start_of_word);
remove_quote(argv[argc]);
argc++;
state = DULL;
}
continue;
case IN_WORD:
if(quote==0 && (c == '\"' ||c == '\''))
quote = c;
else if (quote == c)
quote = 0;
if (isspace(c) && quote==0) {
strncpy(argv[argc],start_of_word, p - start_of_word);
remove_quote(argv[argc]);
argc++;
state = DULL;
}
continue;
}
}
if (state != DULL && argc < argv_max_size){
strncpy(argv[argc],start_of_word, p - start_of_word);
remove_quote(argv[argc]);
argc++;
}
if (quote){
printf("WARNING: Quote is unbalanced. This could lead to unwanted-behavior\n");
for(i = 0;i
Tested with below strings
1. "1 2 3 \'3 4\"567\' \"bol\'obala\" 2x2=\"foo\""
arg 0 = [1]
arg 1 = [2]
arg 2 = [3]
arg 3 = [3 4"567]
arg 4 = [bol'obala]
arg 5 = [2x2="foo"]
2. "./foo bar=\"Hanoi HoChiMinh\" exp='foo123 \"boo111' mixquote \"hanoi \'s\""
arg 0 = [./foo]
arg 1 = [bar="Hanoi HoChiMinh"]
arg 2 = [exp='foo123 "boo111']
arg 3 = [mixquote]
arg 4 = [hanoi 's]
However, Linux shell would remove quotes, even in mixed case, as below when running from cmd line, tested in a RaspberryPi.
./foo bar="Hanoi HoChiMinh" exp='foo123 "boo111' mixquote "hanoi 's"
arg 0 = [./foo]
arg 1 = [bar=Hanoi HoChiMinh]
arg 2 = [exp=foo123 "boo111]
arg 3 = [mixquote]
arg 4 = [hanoi 's]
So if you really want to mimic the whole Linux shell's behavior, just put a little bit more effort into removing quotes remove_quote() function as I leave blank above.