Sujet : Re: Command line globber/tokenizer library for C?
De : Keith.S.Thompson+u (at) *nospam* gmail.com (Keith Thompson)
Groupes : comp.lang.cDate : 10. Sep 2024, 22:37:15
Autres entêtes
Organisation : None to speak of
Message-ID : <87ldzzyyus.fsf@nosuchdomain.example.com>
References : 1
User-Agent : Gnus/5.13 (Gnus v5.13)
ted@loft.tnolan.com (Ted Nolan <tednolan>) writes:
I have the case where my C program is handed a string which is basically
a command line.
>
Is there a common open source C library for tokenizing and globbing
this into an argc/argv as a shell would do? I've googled, but I get
too much C++ & other language stuff.
>
Note that I'm not asking for getopt(), that comes afterwards, and
I'm not asking for any variable interpolation, but just that a string
like, say
>
hello -world "This is foo.*" foo.*
>
becomes something like
my_argv[0] "hello"
my_argv[1] "-world"
my_argv[2] "This is foo.*"
my_argv[3] foo.h
my_argv[4] foo.c
my_argv[5] foo.txt
>
my_argc = 6
>
I could live without the globbing if that's a bridge too far.
What environment(s) does this need to run in?
I don't know of a standard(ish) function that does this. POSIX defines
the glob() function, but it only does globbing, not word-splitting.
If you're trying to emulate the way the shell (which one?) parses
command lines, and *if* you're on a system that has a shell, you can
invoke a shell to do the work for you. Here's a quick and dirty
example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void) {
const char *line = "hello -world \"This is foo.*\" foo.*";
char *cmd = malloc(50 + strlen(line));
sprintf(cmd, "printf '%%s\n' %s", line);
system(cmd);
}
This prints the arguments to stdout, one per line (and doesn't handle
arguments with embedded newlines very well). You could modify the
command to write the output to a temporary file and then read that file,
or you could use popen() if it's available.
Of course this is portable only to systems that have a Unix-style shell,
and it can even behave differently depending on how the default shell
behaves. And invoking a new process is going to make this relatively
slow, which may or may not matter depending on how many times you need
to do it.
There is no completely portable solution, since you need to be able to
get directory listings to handle wildcards.
A quick Google search points to this question:
https://stackoverflow.com/q/21335041/827263"How to split a string using shell-like rules in C++?"
An answer refers to Boost.Program_options, which is specific to C++.
Apparently boost::program_options::split_unix() does what you're looking
for.
-- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.comvoid Void(void) { Void(); } /* The recursive call of the void */