Ří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šší:

if ''příkaz podmínky''
then
''příkaz 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
if ''příkaz podmínky''
then
''příkaz k vykonání''
elif ''druhá podmínka''
''jiný příkaz''
fi

'''Pozor'''

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


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


Ú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?