Выбор ваш. Если вы не цитируете $@
какое-либо из его значений, подвергните дополнительному расширению и интерпретации. Если вы заключите это в кавычки, все переданные аргументы будут воспроизведены в ее расширении дословно. Вы никогда не сможете надежно обрабатывать синтаксические токены оболочки, такие как &>|
и т. Д., Так или иначе, не разбирая аргументы самостоятельно, так что у вас останется более разумный выбор - передать свою функцию одному из:
- Именно слова, используемые при выполнении одной простой команды с
"$@"
.
...или...
- Еще одна расширенная и интерпретированная версия ваших аргументов, которые только затем применяются вместе как простая команда
$@
.
Ни один из способов не является неправильным, если он является преднамеренным и если последствия того, что вы выбираете, хорошо поняты. Оба способа имеют преимущества друг перед другом, хотя преимущества второго редко бывают особенно полезными. Все еще...
(run_this(){ $@; }; IFS=@ run_this 'ls@-dl@/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
... это не бесполезно , просто редко вероятно, будут иметь много использования . И в bash
оболочке, потому bash
что по умолчанию не привязывает определение переменной к своей среде, даже когда указанное определение добавляется перед командной строкой специальной встроенной функции или функции, глобальное значение для $IFS
не затрагивается, и его объявление является локальным только на run_this()
звонок.
Так же:
(run_this(){ $@; }; set -f; run_this ls -l \*)
ls: cannot access *: No such file or directory
... Глобализация также настраивается. Цитаты служат цели - они не зря. Без них расширение оболочки подвергается дополнительной интерпретации - настраиваемой интерпретации. Раньше - с некоторыми очень старыми снарядами - что $IFS
было во всем мире применяются для всех входных данных, а не только расширение. На самом деле, указанные оболочки вели себя очень похоже run_this()
на то, что разбили все входные слова на значение $IFS
. Итак, если вам нужно очень старое поведение оболочки, то вам следует использовать run_this()
.
Я не ищу его, и в данный момент мне трудно найти полезный пример для этого. Я обычно предпочитаю, чтобы команды, которые запускает моя оболочка, были теми, которые я набираю на ней. И так, учитывая выбор, я бы почти всегда run_that()
. Кроме этого...
(run_that(){ "$@"; }; IFS=l run_that 'ls' '-ld' '/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
Почти все может быть процитировано. Команды будут выполняться в кавычках. Это работает, потому что к тому моменту, когда команда фактически выполняется, все входные слова уже подверглись удалению кавычек, что является последним этапом процесса интерпретации ввода оболочки. Таким образом, разница между 'ls'
и ls
может иметь значение только во время интерпретации оболочки - и поэтому цитирование ls
гарантирует, что любой названный псевдонимls
не заменит мое ls
командное слово в кавычках . Кроме этого, единственное, на что влияют кавычки, - это разграничение слов (как и почему работает цитирование переменных / ввода-пробела) и интерпретация метасимволов и зарезервированных слов.
Так:
'for' f in ...
do :
done
bash: for: command not found
bash: do: unexpected token 'do'
bash: do: unexpected token 'done'
Вы никогда не будете в состоянии сделать это с любым из run_this()
или run_that()
.
Но имена функций, или $PATH
команды d, или встроенные команды будут выполняться просто в кавычках или без кавычек, и это именно то, как run_this()
и run_that()
работает в первую очередь. Вы не сможете сделать ничего полезного с $<>|&(){}
любым из них. Если не считать eval
, есть.
(run_that(){ "$@"; }; run_that eval printf '"%s\n"' '"$@"')
eval
printf
"%s\n"
"$@"
Но без этого вы ограничены простыми командами в силу используемых вами кавычек (даже если вы этого не делаете, потому что $@
действует как кавычка в начале процесса, когда команда разбирается на метасимволы) . То же ограничение относится к назначениям и перенаправлениям командной строки, которые ограничены командной строкой функции. Но это не имеет большого значения:
(run_that(){ "$@";}; echo hey | run_that cat)
hey
Я мог бы так же легко <
перенаправить ввод или >
вывод туда, как открыл канал.
В любом случае, здесь нет правильного или неправильного пути - каждый способ имеет свое применение. Просто вы должны написать это так, как вы собираетесь использовать, и вы должны знать, что вы собираетесь делать. Пропуск кавычек может иметь цель - иначе кавычек не было бы вообще - но если вы опускаете их по причинам, не имеющим отношения к вашей цели, вы просто пишете плохой код. Делай, что ты имеешь в виду; Я все равно пытаюсь.
run_that
поведение определенно то, что я ожидал (что если в пути к команде есть пробел?). Если вы хотите другое поведение, конечно , вы бы его конец цитаты на вызова -сайт , где вы знаете , что данные? Я ожидал бы вызвать эту функцию какrun_that ls -l
, которая работает одинаково в любой версии. Есть ли случай, который заставил вас ожидать по-другому?