#c #shell #wildcard #glob
#c #оболочка #подстановочный знак #глоб
Вопрос:
Я пишу свою собственную реализацию очень простой оболочки, но я хочу поддерживать расширение подстановочных слов. Я прочитал ответ здесь, в stackoverflow, в котором предлагается использовать glob(3) для расширения слова во время токенизации команды.
Одним из примеров использования является следующий код, который имитирует ввод текста
ls -l *.c ../*.c
в оболочке:
glob_t globbuf; globbuf.gl_offs = 2; glob("*.c", GLOB_DOOFFS, NULL, amp;globbuf); glob("../*.c", GLOB_DOOFFS | GLOB_APPEND, NULL, amp;globbuf); globbuf.gl_pathv[0] = "ls"; globbuf.gl_pathv[1] = "-l"; execvp("ls", amp;globbuf.gl_pathv[0]);
Есть идеи, как я могу сделать это динамичным и работать с командами, у которых нет подстановочных знаков, а также с теми, у которых есть только 1 или несколько подстановочных знаков?
Является ли glob(3) лучшим способом поддержки расширений подстановочных знаков для моей оболочки или есть лучший способ? Будут ли регулярные выражения лучшей альтернативой? Я пытаюсь учиться здесь, поэтому простите меня, если я что-то неправильно понял, поскольку я относительно новичок в этой области.
Вот мой токенизатор на случай, если это будет полезно:
int build_args(char * cmd, char ** argv) {
char *token;
token = strtok(cmd," ");
int i=0;
while(token!=NULL){
argv[i]=token;
token = strtok(NULL," ");
i ;
}
argv[i]=NULL;
return i;
}
Ответ №1:
Мое экспертное мнение: glob(3)
это не лучший способ, но это самый простой способ. Если вы собираетесь написать совершенно новую оболочку, то, возможно, у нее должны быть некоторые функции, которых нет в некоторых других оболочках, — в противном случае, почему бы не написать оболочку, которая могла бы содержать дополнительные подстановочные знаки, не поддерживаемые glob
. Тогда вы не сможете использовать glob
.
Способ, которым работают оболочки Unix, заключается в том, что вы всегда можете использовать glob в любой командной строке, это не зависит от команд. Поэтому вы даже можете сделать это:
% touch echo Hello world
% ls
echo hello world
% *
hello world
т. е. оператор глобуса, расширенный до echo hello world
которого, был командой, которая была впоследствии запущена.
Но подстановочные знаки не действуют как подстановочные знаки, если они заключены, например, в кавычки.
Комментарии:
1. Спасибо за ваше руководство, но не могли бы вы рассказать мне, как я могу использовать glob(3) для сопоставления и расширения подстановочных знаков? Я выбрал его, потому что он самый простой, я не пытаюсь добавить больше функций, которых еще нет в других оболочках, я просто пытаюсь узнать, как они работают внутри, создавая их самостоятельно.
Ответ №2:
Прочитайте glob(7) — интересная спецификация. Прочитайте также системные вызовы (2). Поиграйте с strace(1) или ltrace(1) в каком-нибудь существующем процессе оболочки (чтобы понять, что на самом деле делает эта оболочка при ее запуске, и что системные вызовы оболочки делают при ее запуске).
Вы можете использовать glob(3) (но см. fnmatch(3) и nftw(3) …). Вы также можете использовать opendir(3) readdir(3) stat(2) closedir(3).
Наконец, GNU bash — это свободное программное обеспечение. Почему бы вам не скачать и не изучить его исходный код? Или загляните в код sash или в код zsh …. Оба имеют открытый исходный код!
Комментарии:
1. Как поможет strace?
2. Что важно в системных вызовах (2)?
3. Оболочки используют системные вызовы.
4. Все использует системные вызовы. Что конкретно актуально?
5. Я рекомендую изучить исходный код существующих оболочек