===== Řídící konstrukce v shellu =====
Dnes si ukážeme podmínku ''if'', a cykly ''for'' a ''while''. Pokud jste již programovali v procedurálním jazyce, jistě vám tyto konstrukce nebudou neznámé. Jen je třeba si zvyknout na trošku odlišnou syntaxi.
Průběžně si také ukážeme několik pomocných příkazů - ''test'', ''expr'', ''seq''
----
==== test ===
Příkaz, jehož aliasem je hranatá závorka - ''['' (pokud je test použitý takhle, musí mít jako poslední parametr opačnou hranatou závorku '']'').
Vrací true / false, ovšem pouze jako návratový kód. Má smysl ho tedy používat právě v podmínkách.
Nejdůležitější použití:
# FUNKCE SE SOUBORY
# Existuje soubor file?
test -e file
# Lze do souboru file zapisovat?
test -w file
# FUNKCE S ŘETĚZCI
# Je proměnná $A neprázdná?
test -n "$A"
# Je proměnná $A prázdná?
test -z "$A"
# FUNKCE S ČÍSLY
# Je $A stejná jako (equals) $B ?
test $A -eq $B
# Je $A menší než (lesser then) $B?
test $A -lt $B
# Je $A menší nebo rovna (lesser or equal then) $B?
test $A -le $B
# Je $A větší než (greater then) $B?
test $A -gt $B
# Je $A větší nebo rovna (greater or equal then) $B?
test $A -ge $B
Více ve [[http://en.wikipedia.org/wiki/Test_%28Unix%29|Wikipedii(en)]]
Použití v podmínce if:
==== if ====
Za ''if'' se píše příkaz, vracející návratový kód 0(true)/jiný (false). Může to být příkaz test, ale ne nutně - vlastně většina příkazů či programů onen návratový kód vrací dle kontextu (například cp ... povedlo se či nepovedlo kopírování?).
Nejjednodušší:
if [příkaz podmínky]
then
[příkazy k vykonání]
fi
Použití ''else'' = jinak:
if [příkaz podmínky]
then
[udělej cosi]
else
[udělej něco jiného]
fi
Použití ''elif'' - další podmínky:
read num
if [ $num -eq 5 ]
then
echo "Cislo je vetsi nez pet"
elif [ $num -lt 5 ]
echo "Cislo je mensi nez pet"
else
echo "Jina moznost"
fi
Pozor:
* Tam kde jsou odřádkování skutečně musí být odřádkování - nebo středník ;
* nezapomeňte na ''fi'' na konci.
=== Příklady ===
if test $A -eq $B
then
echo "A je rovno B!"
else
echo "A se nerovná B."
fi
if [ $A -lt $B ]
then
echo "A je menší než B"
elif [ $A -gt $B ]
echo "A je větší než B"
elif [ $A -eq $B ]
echo "A je stejné jako B"
else
# Možná to nejsou čísla
echo "Err"
fi
=== Úloha: ===
Jak ve scriptu zkontrolovat, zda je parametr $1 číselný?
----
==== expr ====
''expr'' je další užitečný příkaz. Slouží k aritmetice - k počítání s celými čísly.
Například tedy:
expr 5 + 5
expr 3 \* 2
(Nezapomeňme, že hvězdička je [[vyuka:metaznaky_shellu|metaznak shellu]])
Každý člen výrazu musí být samostatný parametr - tedy oddělený od ostatních mezerou. Vypočítat pomocí ''expr'' výraz 5*3+8 lze tedy:
expr 5 \* 3 + 8
Lze použít (odescapované) závorky - pro změnu priority operací:
expr 5 \* \( 3 + 2 \)
#Vypíše 25
expr 5 \* 3 + 2
#Vypíše 17
''expr'' lze samozřejmě jednodušše použít i k počítání s proměnnými. Musí být ale skutečně obsahovat čísla!
#sčítání parametrů
expr $1 + $2
#Zvýšení hodnoty proměnné
a=`expr $a + 1`
----
==== seq ====
Příkaz ''seq'' vypisuje číselnou řadu. Typicky se používá se dvěma parametry - prvním číslem a posledním - například
seq 1 5
#vypíše 1 2 3 4 5
Lze ale i změnit krok (navyšovat o deset a ne o jednu, nebo dokonce záporně) - se třemi parametry jako
''seq PRVNÍ KROK POSLEDNÍ''
seq 10 -2 1
#vypíše 10 8 6 4 2
----
====read====
''read r'' přečte jednu řádku ze vstupu a uloží ji do proměnné r.
Dá se použít například v interaktivní kalkulačce:
#!/bin/sh
echo "Zadej prvni cislo"
read a
echo "Zadej druhe cislo"
read b
echo "Secteno je to `expr $a + $b`"
----
===for===
for promenna in seznam
do
prikaz
done
Přičemž ''seznam'' je jakkoliv dlouhá posloupnost řetězců (oddělených mezerou).
Mohou to být čísla:
for a in 1 2 3 4
do
expr $a * $a
done
Stejně tak to ale mohou být i slova:
for a in stul zidle lampa skrin
do
echo $a je kus nabytku
done
Je tedy vidět, na co se nám hodí příkaz ''seq'' ?
Cyklus "pro všechna čísla od 1 do 100 vypiš jejich dvojnásobky" napíšeme jako:
for a in `seq 1 100`
do
expr $a \* 2
done
----
===while===
while podminka
do
prikaz
done
Cyklus while se opakuje, dokud je podmínka splněna. Je tedy potřeba zajistit, aby někdy splněna byla - jinak cyklus nikdy neskončí.
Podmínka ve ''while'' je to samé, jako podmínka v ''if''. Můžeme tak třeba jednoduše nahradit for cyklus:
a=0
while [ $a -le 100 ]
do
echo $a
a=`expr a + 1`
done
Nebo na čtení ze vstupu pomocí příkazu ''read''
while read radek
do
echo "$radek"
done
Nebo na čtení ze souboru:
while read radek
do
echo "$radek"
done < soubor
(pozor na soubory které nekončí znakem nové řádky!)
=== Úloha:===
Vytvořte script secti.sh, který sečte všechny svoje parametry (které jsou číselné).
Tj. například
./secti.sh 1 4 5 12
22
=== Úloha ===
Script, který očísluje řádky vstupu / souboru.
Tj ze souboru
ahoj
svete
jak se mas?
udělá:
1 ahoj
2 svete
3 jak se mas?