Использование â € œ $ {a: -b} â для присвоения переменной в скриптах
Я рассматривал несколько сценариев, написанных другими людьми (в частности, Red Hat), и многие их переменные назначаются с использованием следующей записи
VARIABLE1="${VARIABLE1:-some_val}"
или некоторые расширяют другие переменные
VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"
В чем смысл использования этой нотации вместо простого объявления значений непосредственно (например, VARIABLE1=some_val
)?
Есть ли преимущества для этой нотации или возможных ошибок, которые могут быть предотвращены?
В этом контексте имеет значение :-
?
3 ответа
Этот метод позволяет присваивать переменной значение, если другая переменная является пустой или не определена. ПРИМЕЧАНИЕ. Эта «другая переменная» может быть той же или другой переменной.
Отрывок
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted.
Otherwise, the value of parameter is substituted.
ПРИМЕЧАНИЕ: Эта форма также работает, ${parameter-word}
. Если вы хотите увидеть полный список всех форм расширения параметров, доступных в Bash, я настоятельно рекомендую вам взглянуть на эту тему в вики Bash Hacker под названием « Расширение параметров ".
Примеры
переменная не существует$ echo "$VAR1"
$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
default value
существует
$ VAR1="has value"
$ echo "$VAR1"
has value
$ VAR1="${VAR1:-default value}"
$ echo "$VAR1"
has value
То же самое можно сделать, оценив другие переменные или выполнив команды в пределах значения по умолчанию для обозначения нотации.
$ VAR2="has another value"
$ echo "$VAR2"
has another value
$ echo "$VAR1"
$
$ VAR1="${VAR1:-$VAR2}"
$ echo "$VAR1"
has another value
Дополнительные примеры
Вы также можете использовать несколько другую нотацию, где это просто VARX=${VARX-<def. value>}
$ echo "${VAR1-0}"
has another value
$ echo "${VAR2-0}"
has another value
$ echo "${VAR3-0}"
0
В приведенном выше $VAR1
& $VAR2
уже были определены с строкой «имеет другое значение», но $VAR3
не определено, поэтому вместо этого использовалось значение по умолчанию 0
.
Другой пример
$ VARX="${VAR3-0}"
$ echo "$VARX"
0
Проверка и назначение с помощью обозначения :=
Наконец, я упомянул удобный оператор, :=
. Это проверит и назначит значение, если тестируемая переменная пуста или неопределена.
Пример
Обратите внимание, что теперь установлен $VAR1
. Оператор :=
выполнил тест и назначение за одну операцию.
$ unset VAR1
$ echo "$VAR1"
$ echo "${VAR1:=default}"
default
$ echo "$VAR1"
default
Однако, если значение установлено ранее, то оно остается в покое.
$ VAR1="some value"
$ echo "${VAR1:=default}"
some value
$ echo "$VAR1"
some value
Справочная таблица Handy Dandy
Ссылки
@slm уже включил документы POSIX - которые очень полезны - но они действительно не расширяются, как эти параметры могут быть объединены, чтобы влиять друг на друга. Здесь еще нет упоминания об этой форме:
${var?if unset parent shell dies and this message is output to stderr}
Это выдержка из еще один ответ , и я думаю, что он очень хорошо демонстрирует, как это работает:
sh <<-\CMD
_input_fn() { set -- "[email protected]" #redundant
echo ${*?WHERES MY DATA?}
#echo is not necessary though
shift #sure hope we have more than $1 parameter
: ${*?WHERES MY DATA?} #: do nothing, gracefully
}
_input_fn heres some stuff
_input_fn one #here
# shell dies - third try doesnt run
_input_fn you there?
# END
CMD
heres some stuff
one
sh: line :5 *: WHERES MY DATA?
Другой пример из
В приведенном выше примере используются все четыре формы подстановки параметров POSIX и их различные Еще одна вещь, которую люди часто не считают о Здесь вы установите некоторые значения по умолчанию и подготовьтесь распечатать их при вызове ... Здесь вы определяете другие функции для вызова функции печати на основе их результатов ... У вас есть все настройки сейчас, так что вот где вы будете выполнять и вытащить ваши результаты. Я расскажу, почему в одно мгновение, но выполнение приведенного выше результата дает следующие результаты: Я пошел в дом твоей матери и увидел Дисней на льду. Если вы выполните каллиграфию , вы добьетесь успеха. то Я пошел на кладбище и увидел Disney on Ice. Если вы выполняете исправление математики , вы добьетесь успеха. Я пошел на кладбище и увидел Диснея на льду. Если вы исправляете математику, вы будете сожалеть об этом. Ключевой особенностью здесь является концепция расширения Если вместо этого вы хотите установить только отмененную переменную, вы должны опустить Возможно, вы заметили, что в приведенном выше примере Но когда sh <<-\CMD
N= #N is NULL
_test=$N #_test is also NULL and
v="something you would rather do without"
( #this subshell dies
echo "v is ${v+set}: and its value is ${v:+not NULL}"
echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}"
${_test:+${N:?so you test for it with a little nesting}}
echo "sure wish we could do some other things"
)
( #this subshell does some other things
unset v #to ensure it is definitely unset
echo "But here v is ${v-unset}: ${v:+you certainly wont see this}"
echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}"
${_test:+${N:?is never substituted}}
echo "so now we can do some other things"
)
#and even though we set _test and unset v in the subshell
echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}"
# END
CMD
v is set: and its value is not NULL
So this $_test:= will equal something you would rather do without
sh: line 7: N: so you test for it with a little nesting
But here v is unset:
So this $_test:= will equal NULL
so now we can do some other things
_test is still NULL and v is still something you would rather do without
или :colon null
. Дополнительная информация приведена в ссылке выше, и здесь она снова . not null
, - это то, как очень полезно она может быть в документе здесь. Вот еще один отрывок из другого ответа : TOP
${parameter:+expansion}
СРЕДНЯЯ
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
НИЖНИЙ
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
Результаты
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
первый запуск:
_less_important_function()'s
_more_important_function():
:
КАК ЭТО РАБОТАЕТ:
_less_important_function()
Вы можете установить переменную в значение только в том случае, если она не установлена или имеет значение null, используя форму
conditional ${parameter} expansion.
: = ${var_name
desired_value}
, а нулевые значения останутся как есть. ON SCOPE:
:colon
и $PLACE
изменится при установке через $RESULT
, хотя parameter expansion
уже вызывается, предположительно устанавливая их при запуске. Причина этого в том, что _top_of_script_pr()
- это функция _top_of_script_pr()
- я заключил ее в ( subshelled )
, а не parens
, используемые для других. Поскольку он вызывается в подоболочке, каждая переменная, которую он устанавливает, является { curly braces }
, и по мере ее возвращения в родительскую оболочку эти значения исчезают. locally scoped
устанавливает _more_important_function()
, это $ACTION
, поэтому он влияет на globally scoped
вторую оценку _less_important_function()'s
, потому что $ACTION
устанавливает _less_important_function()
только через $ACTION
Личный опыт.
Я использую этот формат иногда в своих сценариях, чтобы делать ad-hoc чрезмерное превышение значений, например. если у меня есть:
$ cat script.sh
SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING";
Я могу запустить:
$ env SOMETHING="something other than the default value" ./script.sh`
, не изменяя исходное значение по умолчанию SOMETHING
.