Когда нам нужны фигурные скобки вокруг переменных оболочки?
В сценариях оболочки, когда мы используем {}
при расширении переменных?
Например, я видел следующее:
var=10 # Declare variable
echo "${var}" # One use of the variable
echo "$var" # Another use of the variable
Есть ли существенная разница или это просто стиль? Один предпочтительнее другого?
6 ответов
В этом конкретном примере это не имеет значения. Тем не менее {}
в ${}
полезны, если вы хотите расширить переменную foo
в строке
"${foo}bar"
поскольку "$foobar"
вместо этого будет расширяться foobar
,
Фигурные скобки также безусловно требуются, когда:
- расширение элементов массива, как в
${array[42]}
- используя операции расширения параметров, как в
${filename%.*}
(удалить расширение) - расширение позиционных параметров за пределы 9:
"$8 $9 ${10} ${11}"
Делать это везде, а не только в потенциально неоднозначных случаях, можно считать хорошей практикой программирования. Это как для согласованности, так и для избежания неожиданностей, таких как $foo_$bar.jpg
где визуально не очевидно, что подчеркивание становится частью имени переменной.
Переменные объявляются и присваиваются без $
и без {}
, Вы должны использовать
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.
Это иногда смущало меня - в других языках мы обращаемся к переменной одинаково, независимо от того, находится она слева или справа от присваивания. Но сценарии оболочки разные, $var=10
не делает то, что вы думаете, что делает!
Ты используешь {}
для группировки. Скобки необходимы для разыменования элементов массива. Пример:
dir=(*) # store the contents of the directory into an array
echo "${dir[0]}" # get the first entry.
echo "$dir[0]" # incorrect
Вы также можете сделать некоторые манипуляции с текстом внутри фигурных скобок:
STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}
Результат:
./folder/subfolder/file.txt ./folder
или же
STRING="This is a string"
echo ${STRING// /_}
Результат:
This_is_a_string
Вы правы, в "обычных переменных" это не нужно... Но это более полезно для отладки и чтения сценария.
Фигурные скобки всегда необходимы для доступа к элементам массива и выполнения раскрытия фигурных скобок.
Не переусердствуйте и используйте {}
для расширения переменных оболочки, даже если нет двусмысленности.
Например:
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 to app
fruit=$1le # sets fruit to apple, but confusing
fruit=${1}le # sets fruit to apple, makes the intention clear
Видеть:
Конец имени переменной обычно обозначается пробелом или новой строкой. Но что, если мы не хотим пробела или новой строки после печати значения переменной? Фигурные скобки указывают интерпретатору оболочки, где находится конец имени переменной.
Классический пример 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
(Ответ Фреда уже говорит об этом, но его пример слишком абстрактен)
В соответствии с предложением SierraX и Питера о работе с текстом, фигурные скобки {}
используются для передачи переменной в команду, например:
Допустим, у вас есть файл 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" было заменено.