Когда нам нужны фигурные скобки вокруг переменных оболочки?

В сценариях оболочки, когда мы используем {} при расширении переменных?

Например, я видел следующее:

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable

Есть ли существенная разница, или это просто стиль? Один из них предпочтительнее другого?

Ответ 1

В этом конкретном примере это не имеет значения. Тем не менее, {} в ${} полезны, если вы хотите раскрыть переменную foo в строке

"${foo}bar"

так как "$foobar" вместо этого расширит переменную, идентифицированную foobar.

Фигурные скобки также безусловно требуются, когда:

  • расширяющиеся элементы массива, как в ${array[42]}
  • используя операции расширения параметров, как в ${filename%.*} (удалить расширение)
  • расширение позиционных параметров за пределы 9: "$8 $9 ${10} ${11}"

Делать это везде, а не только в потенциально неоднозначных случаях, можно считать хорошей практикой программирования. Это как для согласованности, так и во избежание неожиданностей, таких как $foo_$bar.jpg, где не очевидно, что подчеркивание становится частью имени переменной.

Ответ 2

Переменные объявляются и назначаются без $ и без {}. Вы должны использовать

var=10

для назначения. Чтобы читать из переменной (другими словами, "расширять" переменную), вы должны использовать $.

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

Это иногда меня путало - на других языках мы ссылаемся на переменную таким же образом, независимо от того, находится ли она слева или справа от назначения. Но shell-scripting отличается, $var=10 не делает то, что вы можете себе представить!

Ответ 3

Вы используете {} для группировки. Скобки необходимы для разыменования элементов массива. Пример:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect

Ответ 4

Вы также можете выполнять манипуляции с текстом внутри фигурных скобок:

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

Результат:

./folder/subfolder/file.txt ./folder

или

STRING="This is a string"
echo ${STRING// /_}

Результат:

This_is_a_string

Вы правы в "обычных переменных" не нужны... Но это более полезно для отладки и чтения script.

Ответ 5

Конец имени переменной обычно обозначается пробелом или новой строкой. Но что, если мы не хотим пробела или новой строки после печати значения переменной? Фигурные скобки указывают интерпретатору оболочки, где находится конец имени переменной.

Классический пример 1) - переменная оболочки без конечных пробелов

TIME=10

# WRONG: no such variable called 'TIMEsecs'
echo "Time taken = $TIMEsecs"

# What we want is $TIME followed by "secs" with no whitespace between the two.
echo "Time taken = ${TIME}secs"

Пример 2) Java classpath с версионными банками

# WRONG - no such variable LATESTVERSION_src
CLASSPATH=hibernate-$LATESTVERSION_src.zip:hibernate_$LATEST_VERSION.jar

# RIGHT
CLASSPATH=hibernate-${LATESTVERSION}_src.zip:hibernate_$LATEST_VERSION.jar

(Ответ Фреда уже говорит об этом, но его пример слишком абстрактен)

Ответ 6

В соответствии с предложением SierraX и Peter о работе с текстом, фигурные скобки {} используются для передачи переменной в команду, например:

Допустим, у вас есть файл sposi.txt, содержащий первую строку итальянского известного романа:

> sposi="somewhere/myfolder/sposi.txt"
> cat $sposi

Ouput: quel ramo del lago di como che volge a mezzogiorno

Теперь создайте две переменные:

# Search the 2nd word found in the file that "sposi" variable points to
> word=$(cat $sposi | cut -d " " -f 2)

# This variable will replace the word
> new_word="filone"

Теперь замените содержимое переменной word на new_word внутри файла sposi.txt.

> sed -i "s/${word}/${new_word}/g" $sposi
> cat $sposi

Ouput: quel filone del lago di como che volge a mezzogiorno

Слово "ramo" было заменено.

Ответ 7

Вьющиеся фигурные скобки всегда необходимы для доступа к элементам массива и выполнения расширения фигурных скобок.

Хорошо быть не слишком осторожным и использовать {} для расширения переменных оболочки, даже если нет места для двусмысленности.

Например:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_arch       # {} is needed since _ can be a part of shell variable name

Итак, лучше написать три строки:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

который определенно более читабелен.

Поскольку имя переменной не может начинаться с цифры, оболочке не требуется {} вокруг пронумерованных переменных (например, $1, $2 и т.д.), Если за таким расширением не следует цифра. Это слишком тонко, и это делает явным использование {} в таких контекстах:

set app # set $ 1 для app fruit = $ 1le # устанавливает фрукты в яблоко, но запутанный fruit = $ {1} le # устанавливает фрукты в яблоко, проясняя намерение


Увидеть: