Ří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, může mít jako poslední parametr opačnou hranatou závorku ''']''' - je dobrým zvykem to tak dělat).
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 Wikipedii(en)
Použití v podmínce if:
if
Za if se píše příkaz, vracející návratový kód 0(false)/1(true). 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šší:
then
''příkaz k vykonání''
fi
Použití ''else'' = jinak
then
''udělej cosi''
else
''udělej něco jiného''
fi
Použití elif - další podmínky
then
''příkaz k vykonání''
elif ''druhá podmínka''
''jiný příkaz''
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 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
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
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
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
Ú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?