Przypisywanie wartości domyślnych do zmiennych powłoki za pomocą jednego polecenia w bash


685

Mam całą masę testów zmiennych w skrypcie powłoki bash (3.00), gdzie jeśli zmienna nie jest ustawiona, to przypisuje domyślną, np .:

if [ -z "${VARIABLE}" ]; then 
    FOO='default'
else 
    FOO=${VARIABLE}
fi

Wydaje mi się, że pamiętam, że w jednej linii jest trochę składni, coś przypominającego trójskładnikowego operatora, np .:

FOO=${ ${VARIABLE} : 'default' }

(choć wiem, że to nie zadziała ...)

Czy jestem szalony, czy może coś takiego istnieje?


1
Dobrym punktem początkowym jest sekcja Shell Parameter Expansion w skorupie bash: tiswww.case.edu/php/chet/bash/bashref.html#Shell-Expansions .
Kemin Zhou,

1
Dokumentacja Gnu.org dotycząca rozszerzenia parametrów powłoki (wskazówka: jest wiele innych fajnych rzeczy, które możesz zrobić!)
JDB wciąż pamięta Monikę

Odpowiedzi:


1228

Bardzo blisko tego, co opublikowałeś, w rzeczywistości:

FOO=${VARIABLE:-default}  # If variable not set or null, use default.

Albo, co nada defaultsię VARIABLErównież:

FOO=${VARIABLE:=default}  # If variable not set or null, set it to default.

64
Gdybym chciał znaleźć to w dokumentacji, po co byłby Google? Googling ze znakami specjalnymi, takimi jak $ {: -}, nie jest bardzo łatwy.
Joshua Olson

20
W odpowiedzi na solarmist: „domyślne przypisanie zmiennej bash” pozwól mi wejść na tę stronę, a przeszukanie strony podręcznika bash za pomocą „zmiennej ass” doprowadziło mnie do właściwej sekcji po ~ piątej „następnej”
Mooshu

57
Zauważ, że nie jest on specyficzny dla basha i będzie działał z całą rodziną powłok. Jest bezpieczny dla skryptów ogólnych.
Jocelyn delalande

16
@solarmist Kluczowym słowem jest „ekspansja parametrów bash”, jeśli chcesz dowiedzieć się więcej o nim i jego towarzyszach.
duleshi

20
Oto bardziej szczegółowe wyjaśnienie na temat unix.stackexchange.com/a/122848/2407
jottr

290

Dla argumentów wiersza poleceń:

VARIABLE=${1:-DEFAULTVALUE}    

która przypisuje VARIABLEwartość pierwszego argumentu przekazanego do skryptu lub wartość, DEFAULTVALUEjeśli taki argument nie został przekazany.


244

Jeśli zmienna jest taka sama, to

: "${VARIABLE:=DEFAULT_VALUE}"

przypisuje DEFAULT_VALUE do VARIABLE, jeśli nie zdefiniowano. Podwójne cudzysłowy zapobiegają globowaniu i dzieleniu wyrazów.

Zobacz także Rozdział 3.5.3, Rozszerzanie parametrów powłoki , w podręczniku Bash.


27
Ta podstępna sztuczka nie była dla mnie oczywista, używając wbudowanego: no-effect do zjedzenia rozszerzenia $ {..} ALE pozostawiając zestaw VARIABLE. Do tej pory robiłem to: VARIABLE = "$ {VARIABLE: -DEFAULT_VALUE}" i czuję się niezdecydowany za dwukrotne użycie VARIABLE.
dino

Okazuje się, że TO NIE ZAWSZE DZIAŁA DLA ZMIENNYCH BUDYNKÓW PODSTAWOWYCH. To bardzo, bardzo dziwne. Obecnie znani mi sąHISTTIMEFORMAT
Otheus,

jak ustawić wiele wartości domyślnych? Próbowałem „: $ {VARIABLE: = DEFAULT_VALUE}: $ {VARIABLE2: = DEFAULT_VALUE2}”, ale wydaje się, że to nie działa ...
Hans

8
@Hans: dwukropek jest poleceniem (które nic nie robi), dlatego jest potrzebny tylko raz. Np.: ${FOO:=DEFAULT1} ${BAR:=DEFAULT2}
Patrik

36

Nawet ty możesz użyć jako wartości domyślnej wartości innej zmiennej

mając plik defvalue.sh

#!/bin/bash
variable1=$1
variable2=${2:-$variable1}

echo $variable1
echo $variable2

uruchom ./defvalue.sh first-value second-valuedane wyjściowe

first-value
second-value

i uruchom ./defvalue.sh first-valuedane wyjściowe

first-value
first-value

28

patrz tutaj pod 3.5.3 (rozszerzenie parametrów powłoki)

więc w twoim przypadku

${VARIABLE:-default}

26

Aby odpowiedzieć na twoje pytanie i na wszystkich podstawieniach zmiennych

echo "$\{var}"
echo "Substitute the value of var."


echo "$\{var:-word}"
echo "If var is null or unset, word is substituted for var. The value of var does not change."


echo "$\{var:=word}"
echo "If var is null or unset, var is set to the value of word."


echo "$\{var:?message}"
echo "If var is null or unset, message is printed to standard error. This checks that variables are set correctly."


echo "$\{var:+word}"
echo "If var is set, word is substituted for var. The value of var does not change."

18

FWIW, możesz podać komunikat o błędzie w następujący sposób:

USERNAME=${1:?"Specify a username"}

Wyświetla taki komunikat i kończy działanie z kodem 1:

./myscript.sh
./myscript.sh: line 2: 1: Specify a username

Bardziej kompletny przykład wszystkiego:

#!/bin/bash
ACTION=${1:?"Specify 'action' as argv[1]"}
DIRNAME=${2:-$PWD}
OUTPUT_DIR=${3:-${HOMEDIR:-"/tmp"}}

echo "$ACTION"
echo "$DIRNAME"
echo "$OUTPUT_DIR"

Wynik:

$ ./script.sh foo
foo
/path/to/pwd
/tmp

$ export HOMEDIR=/home/myuser
$ ./script.sh foo
foo
/path/to/pwd
/home/myuser
  • $ACTION przyjmuje wartość pierwszego argumentu i kończy działanie, jeśli jest pusty
  • $DIRNAME jest drugim argumentem i domyślnie jest to bieżący katalog
  • $OUTPUT_DIRArgument jest 3 lub $HOMEDIR(jeśli jest zdefiniowana) indziej /tmp. Działa to w systemie OS X, ale nie jestem pewien, czy jest przenośny.

17

Jest też sposób na zwięzłe wyrażenie swojej konstrukcji „jeśli”:

FOO='default'
[ -n "${VARIABLE}" ] && FOO=${VARIABLE}

10

Oto przykład

#!/bin/bash

default='default_value'
value=${1:-$default}

echo "value: [$value]"

zapisz to jako script.sh i uczyń z niego wykonywalnym. uruchom go bez parametrów

./script.sh
> value: [default_value]

uruchom to z param

./script.sh my_value
> value: [my_value]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.