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