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?

Edward Q. Mosty
źródło
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.
Andrew McGregor
źródło
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.

miku
źródło
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.

Hans Ginzel
źródło
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
Montells
źródło
28

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

więc w twoim przypadku

${VARIABLE:-default}
ghostdog74
źródło
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."
Guru
źródło
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.
Curtis Mattoon
źródło
17

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

FOO='default'
[ -n "${VARIABLE}" ] && FOO=${VARIABLE}
Rob Wells
źródło
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]
Assaf Shomer
źródło