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

Cykly

for var in list
do
   commands
done

V každé iteraci je do proměnné var přiřazen jeden prvek ze seznamu list a poté je provedeno tělo commands. List je seznam oddělený mezerami. Ten můžeme vytvořit přímo, nebo jej získáme jinak, například pomocí expanze jmen.

# list sestaveny primo
for v in monday tuesday wednesday
do
    echo ${v}
done

# list ziskany expanzi
# pro kazdou (viditelnou) polozku v adresari addr zavolame utilitku file
addr=logs
for f in ${addr}/*
do
    file ${f}
done

Při tvorbě seznamu a jeho zpracování je nutné být opatrný, pokud některé položky obsahují mezery. Takové položky lze v ručně vytvořeném seznamu vyznačit pomocí uvozovek nebo apostrofů. Pokud je seznam vytvořen strojově, tuto možnost nemáme. Dělení řetězce na seznam položek se řídí obsahem proměnné IFS (podrobně viz Dělení slov a IFS). Její hodnotou je řetězec znaků, které chápeme jako oddělovače položek. Výchozí oddělovače jsou mezera, nový řádek a tabulátor. V následujícím příkladu změníme tuto proměnnou tak, abychom mohli přistoupit k jednotlivým adresářům v proměnné PATH.

IFS=:
for dir in ${PATH}
do
    echo -n ${dir}
    echo ": $(ls ${dir} | wc -l) polozek"
done

Při nastavování IFS můžeme narazit na problém, jak tam přidat některý z výchozích znaků. K tomu lze použít znakovou expanzi shellu

$'znak'

Výraz $'\n' tak například expanduje na znak nového řádku; další sekvence jsou v podkapitole Uvozování.

Seznam položek lze produkovat i pomocí příkazu. Na místě list v cyklu můžeme dát spuštění nějakého programu v podshellu a v cyklu zpracovat jeho standardní výstup. V následujícím příkladu zpracujeme obsah souboru /etc/passwd.

# zapamatujeme si puvodni IFS
OLD_IFS=${IFS}

# nova hodnota IFS, soubor prochazime po radcich
IFS=$'\n'

for entry in $(cat /etc/passwd)
do
    # tady nastavime IFS nastavime na dvojtecku
    # nemusime mit strach, ze pokazime IFS pro vnejsi cyklus
    # tam se pamatuje puvodni nastaveni na novy radek
    # tj. vyznam ma pouze hodnota IFS na zacatku cyklu
    IFS=:
    for value in ${entry}
    do
        echo "    ${value}"
    done
done

# tady IFS obsahuje dvojtecku, obnovime puvodni hodnoty
IFS=${OLD_IFS}

Další typ cyklu připomíná jazyk C, nebudeme jej tedy blíže komentovat, čtenáři jistě stačí následující příklad

for (( i=1; i <= 10; i++ ))
do
   echo ${i}
done

Cyklus while funguje také podobně jako v jazyku C. Dokud platí podmínka, opakuje se tělo cyklu. Pro podmínky platí podobné zásady jako pro podmínky konstrukce if. U cyklu navíc můžeme místo podmínky napsat posloupnost řádků, z nichž pouze poslední je interpretován jako podmínka. Zbylé řádky se spustí vždy na začátku iterace, před vyhodnocením podmínky.

# cisla 10...0 se vypisi pred podminkou a uvnitr cyklu,
# cislo -1 se vypise jenom pred podminkou
var=10
while echo "hodnota pred podminkou: ${var}"
      [ ${var} -ge 0 ]
do
    echo "hodnota uvnitr cyklu: ${var}"
    var=$[${var} - 1]
done

Konstrukce until je analogická while s tím, že cyklus končí (nikoliv pokračuje) v momentě, kdy je podmínka pravdivá.


Příkazem break lze okamžitě ukončit vykonávání cyklu, v jehož těle se příkaz nachází. Příkazu break lze volitelně předat numerický argument (přirozené číslo), a ten potom přeruší některý z vnějších cyklů v kódu obsahujícím vnořené cykly. Argument 1 označuje aktuální cyklus, argument 2 cyklus obsahující aktuální cyklus atd.

for v1 in prvni druha treti
do
    for v2 in 10 20 30 40 50
    do
        for v3 in x y z
        do
            break     # prerusi cyklus s promennou v3
            break 1   # prerusi cyklus s promennou v3
            break 2   # prerusi cyklus s promennou v2
            break 3   # prerusi cyklus s promennou v1
        done
    done
done

Příkazem continue lze přerušit vykonávání aktuální iterace cyklu, jako bychom ve skriptu skočili na konec těla cyklu. Podobně jako break lze continue předat numerický argument, určující kterého cyklu se příkaz týká.


Standardní výstup cyklu (tedy vše, co se během cyklu vytiskne) lze přesměrovat do souboru nebo rourou. Přesměrování se píše za klíčové slovo done na konci těla cyklu.

# vypise adresare setrizene podle poctu polozek
IFS=:
for dir in ${PATH}
do
    echo -n ${dir}
    echo " $(ls ${dir} | wc -l)"
done | sort -r -k 2  # tady presmerujeme rourou do prikazu sort