Вибір за вами. Якщо ви не цитуєте$@
жодне його значення, зазнайте додаткового розширення та інтерпретації. Якщо ви цитуєте це, всі аргументи, передані функцією, відтворюються в дослівному розширенні. Ви ніколи не зможете надійно обробляти символи синтаксису оболонки, як &>|
і т. Д., Так чи інакше, не розбираючи аргументи самостійно, - і тому ви залишаєтеся більш розумним вибором передавати свою функцію одним із:
- Саме слова, що використовуються при виконанні однієї простої команди з
"$@"
.
... або ...
- Подальша розширена та інтерпретована версія ваших аргументів, які лише потім застосовуються разом як проста команда
$@
.
Жоден спосіб не є помилковим, якщо він навмисний і якщо ефекти того, що ви обираєте, добре зрозуміли. Обидва способи мають переваги один над іншим, хоча переваги другого рідко можуть бути особливо корисними. Все-таки ...
(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
, яка працює однаково в будь-якій версії. Чи є випадок, який змусив вас очікувати інакше?