Menu

Funkce v shellu

V shellu, stejně jako v kterémkoliv jiném programovacím jazyce můžeme definovat funkce. Členění kódu do funkcí zvyšuje přehlednost, zabraňuje opakování kódu, umožňuje rychleji nacházet chyby a především také umožňuje rozdělit si velký problém na menší podproblémy, se kterými se umíme vypořádat lépe a snadněji. Definice a volání funkce vypadá následovně:

plus() {
    echo $(($1+$2))
}
plus 3 2

Napíšeme tedy jméno funkce, následované () a do složených závorek tělo funkce. Název funkce může být libovolný, pokud ale zvolíme název nějakého už existujícího příkazu, pak při spouštění tohoto příkazu se místo něj spustí naše funkce, která jej překryje. Pokud bychom jej přesto chtěli spustit, museli bychom v takovém případě zadat celou cestu k spustitelnému souboru, např. /bin/ls. Funkce musí být zadefinována ještě předtím, než je poprvé zavolána.

Parametry funkce najdeme v proměnných $1, $2, … – stejně jako u shellového skriptu. Stejně tak seznam všech parametrů najdeme v proměnné $@.

Funkce může vracet návratovou hodnotu pomocí funkce return. Ta okamžitě ukončí provádění funkce. Návratová hodnota je vždy celé číslo a pokud nebyla funkce return zavolána, má se za to že je 0. Návratovou hodnotu posledního spuštěného příkazu nebo funkce zjistíme z proměnné $?. Návratová hodnota by, jak víme, měla znamenat zda funkce skončila úspěšně či ne (s chybou). Pokud chceme, aby funkce vracela jakýkoliv text, číslo apod., je vhodné vrátit je pomocí příkazu echo nebo printf a poté odchytit příkazovou substitucí.

Pozor na to, že všechny proměnné jsou ze své podstaty globální. Pokud tedy zavolám následující kód, bude mi vypsáno 1:

x=0
inc() {
    x=$((x+1))
}
inc
echo $x

Lokální proměnné striktně vzato v shellu neexistují. V bashi si můžete pomoci klíčovým slovem local, pravdou ale je že obecně lepší nápad je odlišit od sebe lokální a globální proměnné jménem.

Vypisování hlášek uvnitř funkcí

Občas potřebujeme vypsat uvnitř funkce nějaký text (např. výzvu k zadání hesla), ale nechceme, aby byl tento text zachycen příkazovou substitucí (např. heslo=$(ziskejHeslo)). V takovém případě se nám hodí vypsat výzvu na standardní chybový výstup. To uděláme pomocí přesměrování stdout na strerr, což už umíme:

ziskejHeslo() {
    printf "Zadej heslo: " 1>&2
    read passwd
    echo "$passwd"
}
heslo=$(ziskejHeslo)