Portál AbcLinuxu, 28. října 2025 02:36
Tentokrát se podíváme na proměnné, napíšeme si náš první skript a vysvětlíme podmínky a cykly.
Jsou pouze jednoho datového typu - řetězec znaků. Některé z nich mohou být určeny jen pro čtení. Proměnné můžeme rozdělit do tří částí.
Vnitřní proměnné shellu. O jejich inicializaci se stará shell.
$ echo $USER
|
Uživatelské proměnné. Jako výše uvedené proměnné se skládají pouze z alfanumerických znaků.
Proměnné speciálního významu, skládají se ze speciálních znaků. Například:
$$ - PID shellu$! - PID posledního procesu, který byl spuštěn na pozadí$? - návratová hodnota posledního dokončeného procesu.Proměnnou můžeme exportovat příkazem export do podřízeného
shellu a příkazem readonly zajistíme, že bude určena
pouze pro čtení (POZOR, toto omezení se nepřenáší do podřízeného shellu).
Když chceme získat hodnotu proměnné, napíšeme před ni znak $.
Ale když jí např. hodnotu přiřazujeme, nepíšeme před ní znak dolaru.
Pro odstranění proměnné použijeme příkaz unset.
$ jedna="Lokální proměnná"
|
Nadešel čas pro napsání a spuštění našeho prvního skriptu. Pak se
ještě na chvíli vrátíme k proměnným. Pojmenujeme ho prvni.sh.
#!/bin/bash
|
Prvním řádkem zajistíme, že náš skript bude opravdu interpretován BASHEM.
To je jediná výjimka při použití znaku #, řádka začínající
tímto znakem je ignorována a slouží k okomentování zdrojového kódu.
Každý správný programátor používá ve svých kódech komentáře.
Když se k němu po čase vrátí, dříve ho pochopí a také zjednoduší
pochopení ostatním. Potřeba naučit se správnému používání komentářů přijde
časem sama. Uvidíte, kde jsou zbytečné a kde naopak velice důležité
(POZOR, komentáře se píší ihned se zdrojovým kódem - podle mě není
dobrý zvyk je psát až po dokončení programu). A nakonec samozřejmě
nezapomeneme vrátit návratový kód exit 0.
Nyní si skript spustíme, ale nejprve musíme přidat právo pro spuštění, protože textový editor toto právo standardně k nově vytvořeným souborům nepřidává.
$ ls -l
|
Nyní, když umíme spouštět skripty, tak si ukážeme na skriptu
promenne.sh ještě několik zajímavých věcí.
#!/bin/bash
prvni="Níže uvedený zá"
echo "${prvni}pis umožní oddělit proměnnou od okolního textu"
# Kdyby byla $druha definována, byla by vrácena její hodnota,
# jelikož není, bude vrácen "náhradní výraz"
echo ${druha-"náhradní výraz"}
echo $druha
# To samé jako předchozí, ale $treti nezůstane nedefinovaná
echo ${treti="náhradní výraz"}
echo $treti
ctvrta="Příšerně žluťoučký kůň úpěl ďábelské ódy."
# Vrátí "náhradní výraz" je-li proměnná definována, jinak
# se nevrací žádná hodnota
echo ${ctvrta+"náhradní výraz"}
echo $ctvrta
# Vypíše délku $ctvrta
echo ${#ctvrta}
# Od konce odstraní nejkraší část $ctvrta, která odpovídá e*
echo ${ctvrta%e*}
# Od konce odstraní nejdelší část $ctvrta, která odpovídá e*
echo ${ctvrta%%e*}
# Od začátku odstraní nejkraší část $ctvrta, která odpovídá *e
echo ${ctvrta#*e}
# Od začátku odstraní nejdelší část $ctvrta, která odpovídá e*
echo ${ctvrta##*e}
exit 0 |
Ještě si skript spustíme pro lepší pochopení.
# ./promene.sh
|
V shellu si ještě vyzkoušíme několik příkazů, abychom pochopili, jak je to s uvozovkami, apostrofy a expanzí.
$ echo $promenna
|
Skript if.sh nám ukáže použití konstrukce
if výraz; then příkazy elif výraz; then příkazy else příkazy fi
#!/bin/bash if [ "$USER" == "root" ]; then echo "Ahoj admine"; fi if [ "$USER" == "root" ]; then echo "Ahoj admine"; else echo "Ahoj uživateli"; fi if [ "$USER" == "root" ]; then echo "Ahoj admine"; elif [ "$USER" == "fuky" ]; then echo "Ahoj Honzíku"; else echo "Ahoj uživateli"; fi exit 0 |
POZOR, mezera za [ je důležitá! Znak [
je totiž program a to, co následuje za ním, jsou jeho argumenty.
$ which [
|
Jak jsem už jednou říkal, všechny proměnné v shellu jsou jednoho
datového typu. To vysvětluje, proč se řetězce a čísla porovnávají
níže popsaným způsobem (výraz, výraz1,
výraz2 vrací řetězec a teprve když ho chceme porovnávat
jako číslo, tak ho shell bere jako číslo, jinak to je stále řetězec).
[ výraz ] - délka řetězce je nenulová[ -z výraz ] - délka řetězce je nulová[ výraz1 == výraz2 ] - řetězce jsou shodné[ výraz1 != výraz2 ] - řetězce jsou různé[ výraz1 -eq výraz2 ] - čísla jsou shodná[ výraz1 -le výraz2 ] - výraz1 <= výraz2[ výraz1 -lt výraz2 ] - výraz1 < výraz2[ výraz1 -ge výraz2 ] - výraz1 >= výraz2[ výraz1 -gt výraz2 ] - výraz1 > výraz2[ výraz1 -ne výraz2 ] - čísla jsou různéTestování souborů.
[ výraz1 -ef výraz2 ] - soubory sdílejí stejný i-uzel[ výraz1 -nt výraz2 ] - první soubor je novější[ výraz1 -no výraz2 ] - první soubor je starší[ -e výraz ] - soubor existuje[ -d výraz ] - soubor je adresář[ -f výraz ] - soubor je obyčejný soubor[ -L výraz ] - soubor je symbolický odkaz[ -w výraz ] - soubor je zapisovatelný[ -x výraz ] - soubor je spustitelnýMísto [ můžete používat test. Jsou to
stejné programy svázané pevným odkazem.
$ if test /usr/bin/test -ef /usr/bin/\[; then echo "Je to opravdu tak..."; fi
|
Podmínky samozřejmě můžete spojovat pomocí operátorů &&
(a zároveň platí) a || (nebo platí).
# if [ $USER == "root" ] && [ $LANG == "cs_CZ" ]; then
|
Na skriptu case.sh se podíváme na použítí konstrukce
case slovo in vzory ) příkazy;; ... esac:
#!/bin/bash
case "$USER" in
root )
echo "Ahoj admine"
;;
fuky )
echo "Ahoj Honzíku"
;;
* )
echo "Ahoj uživateli"
;;
esac
case "$USER" in
root | fuky )
echo "Ahoj Honzíku"
;;
* )
echo "Ahoj uživateli"
;;
esac
exit 0 |
Pro tento díl poslední skript cykly.sh nás zasvětí do
používání cyklů for, while a until.
Podle mě je dobrým zvykem uzavírat proměnné v podmínkách do uvozovek,
protože kdyby proměnná obsahovala např. mezeru nebo nic, došlo by k chybě.
#!/bin/bash
# Vypíše všechny soubory v adresáři s příponou sh
for file in *.sh; do
# Soubor je samozřejmě i adresář a co když nějaký šílenec
# pojmenuje adresář jmeno_adresare.sh
if [ -f "$file" ]; then
echo $file
fi
done
# Do $cislo bude postupně dosazovat čísla
for cislo in 10 20 30 40 50 60 70 80 90 100; do
echo $cislo
done
cislo=0
# Podmínka je splněna jestliže $cislo != 100
while [ "$cislo" -ne 100 ]; do
# Konstrukci $(()) zavedl shell ksh a je rychlejší a méně
# náročná na systémové zdroje než příkaz expr
cislo=$((cislo + 10))
echo $cislo
done
cislo=0
# Cyklus pokračuje dokud není splněna podmínka
until [ "$cislo" -eq 100 ]; do
cislo=$((cislo + 10))
echo $cislo
done
exit 0 |
Do příště máte za domácí úkol všechno si poctivě vyzkoušet.
declare -i proměnná.
$ declare -i a b $ a=10; echo $a 10 $ b=asdgsdg; echo $b 0 $ b="a+3*3"; echo $b 19Vidíme, že integerové proměnné mají zajímavou vlastnost, že se na nich při přiřazení provádí aritmetická expanse -- je to IMHO čitelnější než $((...)). Dále proměnná USER není žádná vnitřní proměnná shellu a LANG bych také neuváděl zrovna jako příklad vnitřní proměnné shellu, protože shell sám ji používá snad jen v lokalizovaných skriptech -- a ten jsem ještě žádný neviděl ;-)
if výraz; then příkazy elif výraz; then příkazy else příkazy fipotřebuje středníky (nebo konce řádků, to je jedno) i před
else a fi.
if příkazy then příkazy elif příkazy then příkazy else příkazy fipřičemž každý příkaz musí být zakončený středníkem.
if false;true; then echo OK; ficož je vlastně stejné jako
false;true;if [ $? -eq 0 ];then echo OK;fi
)
declare -i proměná
pouze shellu říká, že má předpokládat celečíselnou hodnotu proměné a vyhodnotit jí jako aritmetický výraz. Není to, ale v žádném případě definice nového datového typu. Ve
skutečnosti je to stále řetězec ke kterému se shell chová jako k číslu.
$ a=1
$ b=2
$ declare -i c
$ c="$a + $b"
$ echo $c
3
$ d=$(($a + $b))
$ echo $d
3
2. Máte pravdu
if výraz; then příkazy elif výraz; then příkazy else příkazy fi
si každý může vyložit svým způsobem. Slovem příkazy jsem myslel
příkaz1; příkaz2; příkaz3;
y=type_of_y(x) x=type_of_x(y)a proměnná x musí mít tutéž hodnotu co na začátku -- což samozřejmě nefunguje, je-li y integer a x není. Pozn.: Napsal bych, že jde o podmínku nutnou, ale nikoli postačující, ovšem v praxi je to zamotanější, v obskurních jazycích jako C++ či Perl (Tie), se při přiřazení uživatelského typu může stát v podstatě cokoli, takže podmínku nezávislou na konkrétním typovém systému si nedokáži představit...
S tím LANG je to právě naopak než si myslíte.
Právě proto, abyste měl jasně definovaný jazyk výstupů příkazů a aplikací pro následné parsování ve skriptu, je vhodné si na počátku skriptu nastavit LANG=C.
V dnešní době používání linuxu na desktopu s jazykem jiným než EN to dělám zcela běžně.
for ((i=10;i<=100;i=i+10)); do echo $i; done
for cislo in {1,2,3,4,5,6,7,8,9,10}0; do
echo $cislo
done
což je vůbec má oblíbená metoda vytváření seznamů...
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.