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.