Deutsch English Français Italiano |
<87ldzzyyus.fsf@nosuchdomain.example.com> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!2.eu.feeder.erje.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson <Keith.S.Thompson+u@gmail.com> Newsgroups: comp.lang.c Subject: Re: Command line globber/tokenizer library for C? Date: Tue, 10 Sep 2024 14:37:15 -0700 Organization: None to speak of Lines: 73 Message-ID: <87ldzzyyus.fsf@nosuchdomain.example.com> References: <lkbjchFebk9U1@mid.individual.net> MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Tue, 10 Sep 2024 23:37:16 +0200 (CEST) Injection-Info: dont-email.me; posting-host="29df7bbfeaa4d6ddeb7fdca1349b4e93"; logging-data="3326773"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/lJTS4ZtToyQCoCysDZY0p" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:LVWpPmM/TD+tZZ7B/I41wIPhV3k= sha1:qRB5iKcbLKUaNanGS2fPcq+XGz0= Bytes: 3549 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.com void Void(void) { Void(); } /* The recursive call of the void */