Посилання на змінні у сценарії оболонки


10

Якщо в сценарії оболонки я визначаю таку змінну, як FOO=25, чи існує різниця між посиланням на неї як $FOO$і ${FOO}$?


2
Ви не повинні використовувати $зрештою! Це буде розглядатися як звичайний символ, а не як частина імені змінної.
Байт командир

Відповіді:


16

У більшості ситуацій і те, $varі інше ${var}. (Зверніть увагу, що ви не повинні використовувати в $кінці!)

Одним із прикладів, коли вам потрібні фігурні дужки, є те, коли вам потрібно помістити змінну в суцільний рядок.

Приклад:

var=hel
echo ${var}lo

виведе hello.


11

Щоб відповісти на ваше головне питання, ${foo}називається "розширення параметра" . Якщо бути точним, $сам запуск розширення параметрів { }є фактично необов'язковим згідно зі специфікацією POSIX , але може бути корисним для вказівки кінця назви змінної:

$ foo="bar"
$ echo $fooBaz   ## fails, no variable named $fooBaz exists

$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz

В основному, $fooі ${foo}ідентичні. Крім випадків, подібних до вищезазначених, або коли ви робите стрижневі маніпуляції , вони є абсолютно рівнозначними.

Однак вам не слід використовувати жоден із них. Основне правило полягає в тому, що, за дуже малим винятком, ви завжди повинні використовувати "$foo"або "${foo}"ніколи $fooабо ${foo}. Ви завжди повинні цитувати свої змінні, щоб не викликати оператора split + glob (докладніше про це пізніше). Ви, звичайно, не хочете $foo$. Фінал $не має значення:

$ foo="bar"
$ echo "$foo$"
bar$

Отже, хоча змінні, які не котируються, іноді добре:

$ echo $foo
bar

Зазвичай їх немає і дійсно слід уникати:

$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty

$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Зауважте, що дужки також не допомагають тут:

$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi  ## fails
empty

$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Коли ви використовуєте $fooабо ${foo}, оболонка розділить значення, збережене в змінній на пробіл (це можна змінити, встановивши IFSзмінну на щось інше), у список, а потім кожен елемент списку розглядається як глобальний зразок і розшириться на будь-які відповідні файли чи каталоги. Це відоме як оператор split + glob . Для ілюстрації розглянемо каталог з двома файлами:

$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file2

Тепер встановимо змінну на foo *:

$ foo="foo *"

Що станеться, якщо ми спробуємо перевірити, чи існує файл з таким ім’ям?

$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists

Змінна була розбита на fooі *, оскільки *це підстановка, яка відповідає будь-якій рядку, оболонка повідомляє вам, що файл називається foo *exxists. Однак якщо ми це цитуємо правильно, цього не відбувається:

$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file

Це був тривіальний приклад для ілюстрації цього пункту. Уявіть, якби я використовував rmзамість цього echo.

Отже, перше правило: завжди цитуйте свої змінні. Ви можете використовувати "$foo"або, "${foo}"але цитувати це будь-яким способом. Для більш детальної інформації про безпечне використання змінних ознайомтеся з цими публікаціями:


Я не хотів редагувати вашу інакше чудову відповідь, але не повинен $ var="foo *"бути $ foo="foo *"? Ви varніде не користуєтесь .
Джо

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