Мне нужно решить одну задачку. Я уверен, что она решена уже много раз, но я столкнулся с ней впервые, и встретил некоторое затруднение. Мне не хочется решать ее в очередной раз, но хочется воспользоваться уже имеющимся хорошим опытом предшественников.
Есть программка, которая должна запускать другие программки. При этом все аргументы запускаемой программы хранятся конфиругационном файле в одном строковом параметре.
Задачка состоит в том, чтобы нарезать командную строку, полученную из конфигурационного файла на отдельные аргументы для последующей передачи этих агрументов в один из 6 вызовов семейства exec. Как это сделать? Хочется воспользоваться чем-нибудь уже готовым и лучше всего системным, чтобы не пришлось отлавливать потом баги в очередной сторонней библиотеке.
Предшественник, от которого мне досталась эта программка, особо не заморачивался и просто порезал все по пробельным символам, не подумав о том, что некоторые аргументы сами по себе могут содержать пробельные символы.
<skip>
А>Предшественник, от которого мне досталась эта программка, особо не заморачивался и просто порезал все по пробельным символам, не подумав о том, что некоторые аргументы сами по себе могут содержать пробельные символы.
Не указан язык, но я так пронимаю С.
Не знаю поможет или нет .
Я этим очень давно под С пользовался. Понимает кавычки разные, можно указать чем разбито и т.д.
Ну и собственно никакой отвественности не несу .
/* Splits line into parts.*/
int
splitline(char *line,char **args,int maxargs,char *delim)
{
int argcnt = 0;
char c,s;
char *d;
char q = 0;
int qs = 0;
if (line == NULL || delim == NULL)
return argcnt;
for (d = delim; (s = *d++) != 0; ) {
if (s == '\'' || s == '\"') {
qs++;
break;
}
}
/* skip leading delimiters */
cont:
c = *line++;
if (c == 0)
goto done;
for (d = delim; (s = *d++) != 0; ){
/* here we found string in quotes */
if (qs && (c == '\'' || c == '\"')) {
q = c;
c = *line++;
break;
}
if (c == s)
goto cont; /* if ok, try to find next delimiter */
}
if (c == 0)
goto done;
args[argcnt++] = line-1;
if (argcnt == maxargs)
goto done;
for(;;) {
c = *line++;
if (c == 0)
goto done;
if (q && c!= q)
continue; /* check for quote */
if (q)
q = 0; /* if we passed throught quote zero it */
for (d = delim; (s = *d++)!= 0; ) {
if (c == s) {
char *w = line - 1;
*w = '\0';
goto cont;
}
}
}
if (q)
argcnt = 0;
done:
return argcnt;
}
Re[2]: Нарезка командной строки
От:
Аноним
Дата:
23.08.05 12:00
Оценка:
Спасибо, но так я и сам умею. Именно этого и хотелось избежать.
Хотелось бы найти вызов какой-нибудь проверенной бибилиотеки, входящий в большинство UNIX-реализаций.
Программа должна работать под 6 различными UNIX-платформами и под виндами (в данном случае винды не рассматриваем).
P.S. Прошу прощения, что сразу не указал, язык программирования C++.
Здравствуйте, Аноним, Вы писали:
А>Спасибо, но так я и сам умею. Именно этого и хотелось избежать. А>Хотелось бы найти вызов какой-нибудь проверенной бибилиотеки, входящий в большинство UNIX-реализаций. А>Программа должна работать под 6 различными UNIX-платформами и под виндами (в данном случае винды не рассматриваем).
А>P.S. Прошу прощения, что сразу не указал, язык программирования C++.
Прошу прощения, что лезу в чужой монастырь (Юниксов в глаза не видал), но Boost.Program_options -- возможно то, что вам надо.
Здравствуйте, Аноним, Вы писали:
А>Спасибо, но так я и сам умею. Именно этого и хотелось избежать. А>Хотелось бы найти вызов какой-нибудь проверенной бибилиотеки,
входящий в большинство UNIX-реализаций.
Такой думаю нет. Сам С++ вообще-то не очень стандартен для юниксов .
Хотя если интересует просто распространенная библиотека которую _можно_
поставить на любой юникс, то думаю стоит посмотреть на ACE. Ибо я
думаю вам еще много чего может понадобится .
А>P.S. Прошу прощения, что сразу не указал, язык программирования C++.
Во. АСЕ как раз С++ .
Re[4]: Нарезка командной строки
От:
Аноним
Дата:
23.08.05 12:57
Оценка:
Да, я смотрел Boost.Program_Options.
Там есть parse_command_line, parse_config_file и parse_evironment.
Первый парсер сам принимает аргументами argc и argv, а последние два по смыслу не подходят.
Возможно я там что-то недосмотрел, поэтому буду благодарен, если меня ткнут носом.
P.S. Срочность задачи (как обычно ) заставила меня создать эту ветку до того момента, как мне пришло письмо c данными для активации акаунта на этом форуме. Теперь я активировался. Мой позывной — аэропанк
Здравствуйте, aka50, Вы писали:
A>Такой думаю нет.
Есть масса различных командных оболочек, многие из них существуют уже очень давно, все они как-то решают вставшую передо мной задачу. Синтаксис многих командных оболочек весьма похож, если не идентичен.
Это размышление и натолкнуло меня на мысль, что должна существовать какая-то стандартная для POSIX библиотека, решающая эту задачу.
wrote:
> Мне нужно решить одну задачку. Я уверен, что она решена уже много раз, но я столкнулся с ней впервые, и встретил некоторое затруднение. Мне не хочется решать ее в очередной раз, но хочется воспользоваться уже имеющимся хорошим опытом предшественников. > > Есть программка, которая должна запускать другие программки. При этом все аргументы запускаемой программы хранятся конфиругационном файле в одном строковом параметре.
А нельзя ли переписать кофигурационный файл так, чтобы каждый аргумент был на отдельной строке? Тогда его и парсить не нужно.
Builds a counted argument vector (ala argc/argv) from either a string or a set of separate tokens. Can substitute environment variable values for tokens that are environment variable references.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
wrote:
> Мне нужно решить одну задачку. Я уверен, что она решена уже много раз, но я столкнулся с ней впервые, и встретил некоторое затруднение. Мне не хочется решать ее в очередной раз, но хочется воспользоваться уже имеющимся хорошим опытом предшественников. > > Есть программка, которая должна запускать другие программки. При этом все аргументы запускаемой программы хранятся конфиругационном файле в одном строковом параметре. > > Задачка состоит в том, чтобы нарезать командную строку, полученную из конфигурационного файла на отдельные аргументы для последующей передачи этих агрументов в один из 6 вызовов семейства exec. Как это сделать? Хочется воспользоваться чем-нибудь уже готовым и лучше всего системным, чтобы не пришлось отлавливать потом баги в очередной сторонней библиотеке. > > Предшественник, от которого мне досталась эта программка, особо не заморачивался и просто порезал все по пробельным символам, не подумав о том, что некоторые аргументы сами по себе могут содержать пробельные символы.
ME>А нельзя ли переписать кофигурационный файл так, чтобы каждый аргумент был на отдельной строке? Тогда его и парсить не нужно.
ME>-- ME>Maxim Yegorushkin
Вообще можно, но по нескольким причинам не стоит это делать.
1. Заказчик уже приучен к данному формату конфигурационного файла, и он будет недоволен его изменением.
2. По причине 1 нужно веское обоснование изменению формата конфигурационного файла. Привести объяснение вроде "мы не умеем" — означает признаться в своем непрофессионализме.
3. Просто интересно (самому или в вашей помощью) найти красивое решение этой задачи.
eao197 wrote:
> Здравствуйте, MaximE, Вы писали: > > <...код поскипан...> > > Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.
Здравствуйте, aka50, Вы писали:
A>>К сожалению, я не знаком с ACE, буду благодарен за ссылочку A>http://www.cs.wustl.edu/~schmidt/ACE.html
A>А вообще пришло мне тут в голову... а почему бы yacc/lex не воспользоваться? A>Есть везде... да и либ особых не тянет. Проверено временем .
А готовая грамматика для yacc/lex для парсинга аргументов командной строки откуда возмется?
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
eao197 wrote:
> Здравствуйте, MaximE, Вы писали: > > <...код поскипан...> > > Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.
Спасибо! Да, использование default shell — это лучший из имеющихся у меня вариантов.
Но еще красивее было бы решить задачу без его использования.
М.б. все-таки есть библиотека?
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, MaximE, Вы писали:
E><...код поскипан...>
E>Как чисто Unix-овое решение -- самый лучший вариант. Только под Windows без fork-а такого не сделаешь. Разве что под cygwin-ом работать.
На Wiondows можно не отвлекаться.
Там в отдельной обвязке:
#ifdef WIN32
...
#endif
идет вызов CreateProcess, который как раз принимает все аргументы одной строкой.
Что-то я запутался в трех соснах. В исходном сообщении:
Задачка состоит в том, чтобы нарезать командную строку, полученную из конфигурационного файла на отдельные аргументы для последующей передачи этих агрументов в один из 6 вызовов семейства exec. Как это сделать? Хочется воспользоваться чем-нибудь уже готовым и лучше всего системным, чтобы не пришлось отлавливать потом баги в очередной сторонней библиотеке.
Т.е., раз exec, значит нужно запустить новый процесс вместо старого. Тогда вообще ничего мудрить не нужно -- через exec зовем shell и скармливаем ему всю строку параметров, без fork-а.
Или же не вся задача была озвучена.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.