Выбор ваш. Если вы не цитируете $@какое-либо из его значений, подвергните дополнительному расширению и интерпретации. Если вы заключите это в кавычки, все переданные аргументы будут воспроизведены в ее расширении дословно. Вы никогда не сможете надежно обрабатывать синтаксические токены оболочки, такие как &>|и т. Д., Так или иначе, не разбирая аргументы самостоятельно, так что у вас останется более разумный выбор - передать свою функцию одному из:
- Именно слова, используемые при выполнении одной простой команды с
"$@".
...или...
- Еще одна расширенная и интерпретированная версия ваших аргументов, которые только затем применяются вместе как простая команда
$@.
Ни один из способов не является неправильным, если он является преднамеренным и если последствия того, что вы выбираете, хорошо поняты. Оба способа имеют преимущества друг перед другом, хотя преимущества второго редко бывают особенно полезными. Все еще...
(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, которая работает одинаково в любой версии. Есть ли случай, который заставил вас ожидать по-другому?