bash присвоить значение по умолчанию

135

$ {parameter: = word} Назначить значения по умолчанию. Если параметр не установлен или равен нулю, параметру присваивается раскрытие слова. Затем подставляется значение параметра. Позиционные параметры и специальные параметры не могут быть назначены таким образом.

Я думал, что могу использовать эту функцию для записи ${LONG_VARIABLE_NAME:=hello}вместо более длинного LONG_VARIABLE_NAME=${LONG_VARIABLE_NAME:-hello}, но теперь bash также пытается выполнить 'hello', и это дает команду, которая не найдена. Есть ли способ избежать этого? Или мне придется придерживаться последнего? Может ли кто-нибудь привести пример, когда назначение по умолчанию действительно полезно?

zedoo
источник
13
При цитировании текста полезно включать ссылку на источник.
Jonathon Reinhart

Ответы:

202

Используйте двоеточие:

: ${A:=hello}

Двоеточие - это пустая команда, которая ничего не делает и игнорирует свои аргументы. Он встроен в bash, поэтому новый процесс не создается.

CAMH
источник
93
Я не могу не заметить, что : ${A:=hello}это ровно столько, сколько A=${A:-hello}. Также кажется, что последнее немного менее эзотерично, а его цель более ясна. Использование :, которое в основном не работает, кажется глупым по сравнению с тем, как OP делал это раньше.
Дэн Молдинг,
5
@camh: Согласен. Я вижу, где, если бы у вас было много переменных, которые нужно инициализировать по умолчанию, и у них были длинные имена, :подход был бы предпочтительнее как для ввода, так и для чтения. Да, похоже, в этой области Bash можно было бы немного улучшить.
Дэн Молдинг,
17
@DanMoulding: насчет : ${VERY_LONG_VARIABLE_NAME:=hello}VS.: VERY_LONG_VARIABLE_NAME=${VERY_LONG_VARIABLE_NAME:-hello}. Надеюсь, вы используете в своем коде описательные имена переменных :)
pihentagy 05
18
Не только короче, но менее подвержен ошибкам: VERY_LONG_VARIABLE_NAME=${VERY_LOGN_VARIABLE_NAME:-hello}. К сожалению.
chepner
5
Преимущество такого A=$A:-helloподхода в том, что он самодокументируется при запуске с set -x. То есть, присвоение будет напечатано, а A=helloкоманда null будет печатать только значение ( hello).
lmsurprenant
107

Пожалуйста , посмотрите на http://www.tldp.org/LDP/abs/html/parameter-substitution.html примеры

${parameter-default}, ${parameter:-default}

Если параметр не установлен, используйте значение по умолчанию. После звонка параметр все еще не установлен.
Обе формы почти эквивалентны. Дополнительное значение :имеет значение только тогда, когда параметр был объявлен, но имеет значение null.

unset EGGS
echo 1 ${EGGS-spam}   # 1 spam
echo 2 ${EGGS:-spam}  # 2 spam

EGGS=
echo 3 ${EGGS-spam}   # 3
echo 4 ${EGGS:-spam}  # 4 spam

EGGS=cheese
echo 5 ${EGGS-spam}   # 5 cheese
echo 6 ${EGGS:-spam}  # 6 cheese

${parameter=default}, ${parameter:=default}

Если параметр не установлен, установите значение параметра по умолчанию.
Обе формы почти эквивалентны. : Имеет значение только тогда, когда параметр был объявлен и имеет значение null

# sets variable without needing to reassign
# colons suppress attempting to run the string
unset EGGS
: ${EGGS=spam}
echo 1 $EGGS     # 1 spam
unset EGGS
: ${EGGS:=spam}
echo 2 $EGGS     # 2 spam

EGGS=
: ${EGGS=spam}
echo 3 $EGGS     # 3        (set, but blank -> leaves alone)
EGGS=
: ${EGGS:=spam}
echo 4 $EGGS     # 4 spam

EGGS=cheese
: ${EGGS:=spam}
echo 5 $EGGS     # 5 cheese
EGGS=cheese
: ${EGGS=spam}
echo 6 $EGGS     # 6 cheese

${parameter+alt_value}, ${parameter:+alt_value}

Если параметр установлен, используйте alt_value, иначе используйте пустую строку. После звонка значение параметра не изменилось.
Обе формы почти эквивалентны. : Имеет значение только тогда, когда параметр был объявлен и имеет значение null

unset EGGS
echo 1 ${EGGS+spam}  # 1
echo 2 ${EGGS:+spam} # 2

EGGS=
echo 3 ${EGGS+spam}  # 3 spam
echo 4 ${EGGS:+spam} # 4

EGGS=cheese
echo 5 ${EGGS+spam}  # 5 spam
echo 6 ${EGGS:+spam} # 6 spam
Джонатан Л
источник
20

Расширение параметра значения по умолчанию часто полезно в сценариях сборки, подобных приведенному ниже примеру. Если пользователь просто вызывает скрипт как есть, perl не будет встроен. Пользователь должен явно установить WITH_PERLзначение, отличное от «no», чтобы он был встроен.

$ cat defvar.sh
#!/bin/bash

WITH_PERL=${WITH_PERL:-no}

if [[ "$WITH_PERL" != no ]]; then
    echo "building with perl"
    # ./configure --enable=perl
else
    echo "not building with perl"
    # ./configure
fi

Сборка без Perl

$ ./defvar.sh
not building with perl

Сборка с Perl

$ WITH_PERL=yes ./defvar.sh
building with perl
SiegeX
источник