Як використовувати змінні всередині одиничних лапок


11

У мене є додаток, який приймає в якості атрибутів введення подвійні лапки, вбудовані в єдині лапки. Візьмемо для прикладу цю правильну команду:

command -p 'cluster="cl1"'

Щоб автоматизувати це, я створив файл bash, використовуючи $CLUSTERяк змінну. Як має бути моя команда? Іншими словами, що я повинен поставити замість cl1?

Зауважте, що якщо я змінив вищевказану команду, вона не буде прийнята. Наприклад: command -p "cluster=cl1"не приймається


2
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
mikeserv

Ще одна можливість (якщо ви віддаєте перевагу зберігати cliбез лапок всередині CLUSTERзмінної):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
jimmij

Нарешті я знайшов правильну відповідь. Дякую @jimmij.
Mohamad-Jaafar NEHME

Відповіді:


8

Схоже, ваша команда, можливо, встановлює змінні середовища на основі аргументів, наведених у командному рядку. Ви можете зробити це:

CLUSTER=cl1; cluster=$CLUSTER command

... і встановити його середовище для виклику.

В іншому випадку цитати оболонки зазвичай розмежовують аргументи або уникають інших спеціальних символів оболонки від інтерпретації оболонки. Ви можете містити (і, отже, уникати) різного роду цитати оболонок в інших видах на основі різних правил:

  • "''''" - рядок з м'яким цитуванням може містити будь-яку кількість твердих цитат.
  • "\""- \зворотна косою рисою може вийти з "м'якої цитати в "рядку з м'яким котируванням.
    • У цьому контексті \\зворотний косий рядок також уникає себе, \$маркер розширення та \newlines, як зазначено нижче, але інакше трактується буквально.
  • "${expand} and then some"- рядок із цитатами з м'яким цитуванням може містити інтерпретоване $розширення оболонки .
  • '"\'- 'рядок з твердим котируванням може містити будь-який символ, окрім 'твердої цитати.
  • \- без котирується косої риски буде уникнути будь-якого наступного символу для буквальної інтерпретації - навіть іншого зворотного \nкосого кута - за винятком лінії ел.
    • У \\nвипадку ewline і \зворотна косої лінії, і \newline повністю видаляються з отриманої інтерпретованої команди.
  • ${parameter+expand "$parameter"}- лапки, отримані внаслідок розширення оболонки, майже ніколи не служать маркерами розмежування, за винятком кількох спеціальних випадків. Я не буду ризикувати далі описати це.

Я вважаю дивним, що будь-яка програма буде інтерпретувати цитати у своїх аргументах командного рядка. Така практика не має великого сенсу в тому, що - принаймні для оболонок - головна мета цитати, як правило, обмеження аргументу. Коли Ви телефонуєте, однак, аргументи завжди вже розмежовані з \0NULсимволами і тому цитати не можуть служити багато цілей.

Навіть оболонка, як правило, турбується лише інтерпретувати цитати в одному з своїх аргументів виклику, коли вона викликається -cкомутатором, що означає, що її перший операнд - це насправді сценарій оболонки, який він повинен працювати при виклику. Це випадок дворазово оцінених даних.

Все, що було сказано, ви можете зробити ряд речей, щоб передати буквальні цитати через аргументи в командному рядку. Наприклад:

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"

Як я зазначав у коментарі раніше, ви можете містити "цитати в межах розширення, яке саме "цитується.

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""

Ви можете уникнути "за допомогою \зворотної косої межі всередині "рядка в лапках.

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'

Ви можете чергувати і об'єднувати стилі цитування, щоб досягти бажаного кінцевого результату, як зазначає @jimmij вище .

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )

Ви можете вимкнути як генерування імен файлів, так і $IFSрозбиття, тим самим уникаючи необхідності цитувати цитати $expansion- і так лише цитувати цитати. Це, мабуть, надмірність.

Останнє, є ще один тип цитата оболонки, який може бути використаний. Як я вже зазначав, sh -c "$scriptlet"форма виклику оболонки часто використовується для надання сценарію оболонки в командному рядку. $scriptletОднак, коли стає складніше - наприклад, коли лапки повинні містити інші лапки - часто може бути вигідним використання тут документа, а sh -sзамість цього - де оболонці спеціально доручено призначити всі наступні операнди позиційним параметрам, як це робиться у -cвипадку а ще взяти його сценарій stdin.

Якщо ваша команда повинна інтерпретувати лапки таким чином, то я вважаю, що це краще, якщо це можна зробити у файловому вводі. Наприклад:

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT

Якщо ви не цитуєте розмежувач a, <<here-documentтоді весь його вміст трактується майже так само, як вони були "цитованими - за винятком того, що самі "подвійні лапки не розглядаються спеціально. І якщо ми catзамість цього запустимо вище :

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT

... він друкує ...

cluster="cl1"

1

Як mikeserv писав:

 CLUSTER='"cl1"'; command -p "cluster=$CLUSTER" 

«Подвійна лапки» кожен літерал , який містить прогалини / метасимволу і кожне розширення: "$var", "$(command "$var")", "${array[@]}", "a & b". Використовуйте 'single quotes'для коду або буквального $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. Дивіться
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words


Ви маєте рацію, дякую. Але що робити з автоматизацією? Припустимо, я хочу прочитати CLUSTER? Я знову застрягну в тій же проблемі: змінна всередині одинарних цитат
Mohamad-Jaafar NEHME

@Moi - автоматизація не є великою справою, хоча вам доведеться очистити змінну "символів - достатньо лише першого та останнього. Справжня проблема тут у тому, що ваш додаток інтерпретує цитати в аргументі. Інтерпретація цитати в аргумент майже ніколи не є хорошою ідеєю, оскільки цитата повинна бути лише засобом розмежування аргументу - а при виклику розмежування виконується \0NULs у кожному випадку. Можливо, є кращий спосіб передати потрібну інформацію додатку? Як, command --'script=/path/to/some/file'чи щось?
mikeserv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.