Чому bash змінна розширення зберігає лапки?


12
> echo "hi"
hi
> VAR='echo "hi"'
> $VAR
"hi"

Чому вихід вищевказаних команд різний?

Аналогічна річ відбувається з одинарними цитатами:

> VAR="echo 'hi'"
> $VAR
> 'hi'

6
Будь ласка, не впадайте в звичку вставляти фрагменти виконуваних скриптів у змінні. Це в кращому випадку evalє
jw013

@ jw013 Добрий момент та чудові статті. Мені подобається цитата "Змінні містять дані, функції утримують код." з першого посилання, але для мого використання дані, які надаються функції (в даному випадку, at), є кодом. Якісь поради щодо безпечнішого способу організації / збору коду, який буде надано at?
Cory Klein

atприймає shсинтаксис як вхідний. Таким чином, генерація вводу atозначає генерування дійсного, правильно цитованого shсинтаксису з довільного введення, що не є тривіальним, тому я б спробував уникнути цього, якщо це можливо. Це дійсно допоможе, якби ви могли трохи детальніше розповісти про те, що ви намагаєтеся досягти.
jw013

Вибачте, я не хотів відволікатися на занадто багато деталей, але те, що я роблю, насправді не складне, IMO. Я створюю сценарій, який займає "час" і "повідомлення". Потім він працює atза заданий "час" і каже atвиконувати команду dzen2. dzen2приймає "повідомлення" від stdin, а також використовує деякі інші статичні параметри. Складність полягає в тому, що мені потрібно ввести в dzen2команду параметр "message" від користувача , але я насправді не працюю dzen2сам, я говорю atце зробити.
Cory Klein

Відповіді:


16

Додаткова пара лапок споживається лише додатковим кроком оцінювання. Наприклад, змушені eval:

bash-4.2$ VAR='echo "hi"'

bash-4.2$ $VAR
"hi"

bash-4.2$ eval $VAR
hi

Але взагалі погана ідея ставити команди з параметрами в один рядок. Замість цього використовуйте масив:

bash-4.2$ VAR=(echo "hi")

bash-4.2$ "${VAR[@]}"
hi

1
Важливо також зазначити, що котирування оцінюються по-різному; подвійні лапки (") дозволяють оцінювати доданий рядок, одинарні лапки (") друкують рядок як буквальний. Приклад: "$(ls)"і '$(ls)'. Це причина, чому цитати з'являються в оригінальних прикладах запитань.
Джозеф Керн,

Масив також є джерелом проблем. Код належить до функцій, дані змінним. Приклад, який ви представляєте, працює лише тому, що лапки видаляються при розщепленні масиву. A printf '<%s> ' "${VAR[@]}"покаже, що цитати вже видалено. Якщо ви встановите, що VAR VAR=(echo \"hi\")фактично має цитати, знову з’явиться та сама проблема, $ ${VAR[@]}надрукується"hi"

9

Видалення цитат відбувається лише на початкових словах, а не на результатах розширень. Цитати, що входять до складу розширених змінних, недоторкані.


2

Якщо трохи відступити назад, ви можете зрозуміти, чому підміна змінної абсолютно повинна зберігати лапки.

Суть цитат у оболонці Unix / Linux / BSD полягає в тому, щоб зберегти фрагменти рядка разом, які в іншому випадку будуть розбиратися як декілька рядків. Оскільки оболонка за замовчуванням використовує пробіл як роздільник токенів, рядок з пробілами (на зразок "один два три"), якщо їх не цитувати або як-небудь уникнути, буде розбиратися як 3 рядки: "один", "два" і "три".

Якщо програміст хоче ввести рядок зі значенням певної змінної, інтерпольованої:

VAR=two
STRING="one $VAR three"

оболонка абсолютно не повинна видаляти лапки: рядок, що містить пробіли, буде розбиратися у вигляді 3 менших рядків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.