Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Větvení

Bash podporuje následující formy příkazu if.

# bez else
if tst
then
   commands-true
fi

# s else vetvi
if tst
then
   commands-true
else
   commands-false
fi

Pokud je na místě tst proměnná, je podmínka pravdivá, pokud je proměnná neprázdná. Je-li tst příkaz, je spuštěn. Pokud je jeho návratová hodnota 0, provede se blok commands-true. V opačném případě se ve verzi s else větví provede commands-false. Existuje syntax i pro žebříkovou verzi konstrukce, kde je else if nahrazeno elif

# zebrik
if tst
then
   commands
elif tst
then
   commands
else
   commands
fi

Příkladem utility, kterou lze použít na místě tst, je grep. Pokud totiž nalezne aspoň jednu shodu, její návratová hodnota je 0, jinak je nenulová. Následující skript otestuje, jestli je v systému uživatel s vybraným jménem.

ouruser='franta'

if grep -q "^${ouruser}:" /etc/passwd
then
    echo "uzivatel ${ouruser} existuje"
else
    echo "uzivatel ${ouruser} neexistuje"
fi

Pro ověřování obecnějších podmínek lze použít utilitu test, která se používá ve formě1

[ expression ]

Za otevírací závorkou a před uzavírací závorkou musí být mezery. Pokud test vyhodnotí expression jako pravdivé, skončí s návratovou hodnotou 0, jinak s hodnotou nenulovou. Na místo expression lze napsat celou řadu podmínek, užitečná je tady manuálová stránka programu test. Existují podmínky pro celá čísla, řetězce, testy existence, práv a jiných vlastností souborů. Ve výrazu tst v konstrukci if lze použít logických operátorů pro spojky a (&&) a nebo (||). V následujícím kódu jsou příklady použití několika testů.

#
# numericke porovnavani
#

# tady si je pouzito && k vytvoreni konjunkce
# n1 -ge n2 je test, jestli n1 >= n2
if [ ${a} -ge ${b} ] && [ ${a} -ge ${c} ]
then
    echo "nejvetsi je a s hodnotou ${a}"
elif [ ${b} -ge ${c} ]
then
    echo "nejvetsi je b s hodnotou ${b}"
else
    echo "nejvetsi je c s hodnotou ${c}"
fi

#
# prace s retezci
#
x=cecil
y=josef
z=""

# proc nize expanzi promenne davame do ""?
# aby test chapal expanzi promenne jako retezec,
# ma nevhodny tvar, napriklad obsahuje vice slov, atd.
# alternativou je pouzit modernejsi [[ -n  ${x} ]]
# (to potom ovsem neni program test, je to bash builtin)

# delky retezcu
if [ -n "${x}" ]
then
    echo "x je neprazdny"
fi

if [ -z "${z}" ]
then
    echo "z je prazdny"
fi

# rovnost
if [ "${x}" != "${y}" ]
then
    echo "x a y jsou ruzne"
fi

if [ "${x}" = "${y}" ]
then
    echo "x a y jsou stejne"
fi

# lexikograficke porovnani
# operator porovnani < je nutne backquotovat, jinak je bran jako presmerovani
if [ "${x}" \< "${y}" ]
then
    echo "x je mensi nez y"
fi

#
# prace se soubory
#

# vypise obsah adresare, pokud existuje
# dalsi testy existence a vlastnosti souboru a adresaru jsou analogicke
addr=logs
if [ -d  "${addr}" ]
then
    ls ${addr}
fi

# porovnani stari souboru
if [ "${file1}" -ot "${file2}" ]
then
    echo "soubor ${file1} je starsi nez ${file2}"
fi

Bash obsahuje následující rozšíření, která nemusí být podporována v jiných shellech.

  • dvojí obyčejné závorky na místě tst (tj. výraz (( expression ))): lze použít některé aritmetické, bitové a logické operátory, které test neumí.

  • dvojí hranaté závorky na místě tst (tj. výraz [[ expression ]]): pro řetězcové porovnávání, obsahuje to co test, navíc lze kontrolovat shodu s regulárním výrazem, řeší problémy s expanzí a mezerami při porovnávání řetězců a cest.


Analogií konstrukce switch z jazyka C je v Bashi case. Umožňuje porovnat hodnotu s jinými hodnotami (jako řetězce) a v případě shody provést blok příkazů. Syntax příkazu je následující.

case val in                  # val je hodnota, kterou porovnavame
  pattern1)                  # hodnoty, se kterymi porovnavame jsou ukonceny )
      cmd1                   # nasleduje blok prikazu
      [...]
      cmdk  ;;               # ktery je ukoncen dvema stredniky
  pattern2 | pattern3)       # lze uvest vice hodnot oddelenych |, staci shoda s jednou
      cmds ;;
  *)                         # * se shoduje se vsim, je to analogie default z C
      cmds ;;
esac

Je důležité si uvědomit, že na val i pattern je aplikována expanze.

Konstrukce se používá na místech, kde bychom jinak použili dlouhou if konstrukci s mnoha elif větvemi, jak v následujícím kódu.

month=June

case ${month} in
    January | March | May | July | August | October | December)
        echo "${month} has 31 days" ;;
    February)
        echo "${month} has 28 or 29 days"  ;;
    April | June | September | November)
        echo "${month} has 30 days" ;;
    *)
        echo "${month} is not a valid month"
esac

Typické použití ve skriptech je při zpracování argumentů, jak uvidíme v kapitole Vstupní argumenty.


  1. Existuje program se jménem [, který se chová jako test. ↩