Toto je druhý článek ze série zaměřené na skriptování Gnu Bash. V prvním článku o skriptování bash jsme právě vytvořili ten nejjednodušší skript:jednoduché příkazy, jeden po druhém. Také jsme viděli použití některých proměnných. Tento článek se bude zabývat řídicími strukturami bash.
Řídicí struktury
Jak jsem řekl v předchozím článku, lenost je klíčem k úspěchu. Pokud musím spustit nějaké příkazy, o chvíli později stejné příkazy ve stejném pořadí, až nastane potřetí, otevřu textový editor a vložím tyto příkazy, abych to uložil jako skript.
O několik dní později tento skript začíná růst, a to jak v rozšíření, tak ve složitosti. Potřebuji způsoby, jak řídit tok provádění, například:
- pokud se něco stane, udělejte něco, nebo pokud se něco nestane, udělejte něco jiného;
- když se něco děje, dělejte něco znovu a znovu nebo dělejte něco znovu a znovu;
- nebo v závislosti na hodnotě proměnné nebo na tom, co se stalo, udělejte to či ono nebo ono,
- atd
K tomu jsou určeny řídicí struktury bash (ve skutečnosti v bash nebo jakémkoli jiném programovacím jazyce). Nejprve však potřebujeme vědět o:
Stav ukončení
Z manuálové stránky bash:
«Stav ukončení provedeného příkazu je hodnota vrácená systémovým voláním waitpid nebo ekvivalentní funkcí. Stavy opuštění jsou mezi 0 a 255. (…) nulový stav ukončení označuje úspěch (nebo se rovná „pravdivému“). Nenulový stav ukončení označuje selhání (nebo se rovná 'false').(…. Například:) Pokud příkaz není nalezen, podřízený proces vytvořený k jeho provedení vrátí stav 127. Pokud je příkaz nalezen, ale není spustitelný, návratový stav je 126 ».
tl;dr:výstupní status 0 znamená true , úspěch; jakákoli jiná hodnota znamená false . Je důležité se to naučit, protože provádět správná/nepravdivá rozhodnutí znamená kontrolovat stav ukončení příkazu.
Bash ukládá stav ukončení posledního provedeného příkazu do $? proměnná.
if-then-else
Toto je pokud se něco stane (něco se stane znamená příkaz se stavem ukončení nula) udělejte něco nebo udělejte jinou věc. Syntaxe je:
if command then command1 command2 ... else commandA commandB ... fi
Jak můžete vidět na snímku obrazovky, lze jej napsat na jeden řádek a každý příkaz oddělit středníkem:
příkazif command; then command1; command2;...; else commandA; commandB;...;fi
V závislosti na složitosti bloku if-then může být snazší nebo obtížnější přečíst styl „oneliner“.
Co když chcete spustit nějaký příkaz, když se něco stane, spusťte jiný příkaz pouze pokud něco jiného se děje? použijte klíčové slovo elif (else if):
if command then command1 command2 ... elif other_command commandA commandB ... else another block of commands fi
Blok if-then-else končí klíčovým slovem fi (pokud je to obráceně).
Porovnání řetězců a čísel
Pamatujete si proměnné? často se něco stane je, že v závislosti na hodnotě proměnné chceme spouštět nějaké příkazy nebo jiné.
Pro porovnání, zda se řetězec rovná nějakému slovu nebo číslu je nižší než jiné, použijeme příkaz test . Obecná syntaxe je:
test expression
Pokud výraz je vynecháno, považuje se za nepravdivé (stav ukončení> 0). Pokud výraz je to jen řetězec textu, to je pravda. To může být složité, například:
$ test false; echo $? 0
Netestujeme výstupní stav příkazu false (existuje příkaz false ), ale řetězec false proti ničemu. Dalším způsobem spuštění příkazu test je uzavření výrazu do hranatých závorek. Tento jiný způsob je snazší číst uvnitř bloku if-then-else.
operandy | pravda, pokud |
výraz | pravda |
! výraz | false (neguje výraz) |
výrazA -a výrazB | A. oba výrazy jsou pravdivé |
výrazA -o výrazB | Nebo. jeden z výrazů je pravdivý |
řetězec1 =řetězec2 | oba řetězce jsou stejné |
řetězec1 !=řetězec2 | řetězce jsou různé |
int1 -eq int2 | celé číslo1 se rovná celému číslu2 |
int1-ge int2 | int1>=int2 |
int1 -gt int2 | int1> int2 |
int1 -le int2 | int1 <=int2 |
int1 -lt int2 | int1 |
int1 -ne int2 | int1 se nerovná int2 |
-e soubor | soubor existuje |
adresář -d | soubor existuje a je to adresář |
Výrazů je více, právě ty považuji za důležitější. Přečtěte si manuálovou stránku pro test, abyste se naučili další výrazy.
Dávejte pozor, aby mezi oběma hranatými závorkami a výrazem byla mezera. Nyní můžeme pomocí testu něco udělat na základě hodnoty proměnné. Například:
případ
Když chceme otestovat proměnnou proti několika hodnotám, můžeme do našeho bloku if-then-else přidat více elif takto:
if [ $a = "value1" ] then command1 for value1 ... commandN for value1 elif [ $a = "value2" ] then command1 for value2 ... commandN for value2 ... elif [ $a = "valueN" ] then command1 for valueN ... commandN for valueN else command1 for every other value ... commandN for every other value fi
Nebo můžeme nahradit příkazem case, který se snáze čte a píše:
case expression in value1) command1 for value1 ... commandN for value1 ;; value2) command1 for value2 ... commandN for value2 ;; ... *) command1 for every other value ... commandN for every other value ;; esac
Také méně stisknutí kláves, nezapomeňte být dostatečně líní, aby počítač pracoval za vás. Poslední hodnota * je výchozí případ, všechny ostatní hodnoty, které se předtím neshodovaly. Případ pozpátku, esac , je analogický s prohlášením fi. Pokud ;; Pokud je použit operátor, po první shodě vzoru se již nepokusí o žádné další shody. Pro otestování dalšího vzoru použijte ;;* operátor. Například:
dokdy a do
Zatímco je něco dělat znovu a znovu, zatímco se něco děje. A dokud je to stejné, ale negované (dělejte něco znovu a znovu, zatímco se něco neděje). Obecná syntaxe je:
while command do command1 command2 ... commandN done
Chcete-li něco udělat, zatímco se neděje (tj. stav exist je jiný než 0), nahraďte while za dokud. Podívejte se na několik příkladů:
Všimněte si, že nevytvářeli stejný výstup. V bloku while, když $a dosáhne hodnoty 4, není více než 4, takže test je vyhodnocen jako false (a výstupní kód je> 0). Na bloku till, když $a dosáhne hodnoty 4, není větší než 4.
Hodiny ve vašem terminálu
Někdy testuji cronjob a to mě znervózňuje, dokud nebude proveden. Jako podmínku používám příkaz true (který, jak jste si možná mysleli, vytváří stav ukončení 0) a spouštím datum příkazu znovu a znovu:
while true do date sleep 1 clear done
To by běželo déle, ale mohu přerušit pomocí ctrl-c.
pro-in -dělat
Tento druh smyčky iteruje přes poskytnutý seznam a přiřazuje každou položku do proměnné. Syntaxe:
for i in list of words do command1 ... commandN done
To je lépe vidět na příkladu:
Zůstaňte naladěni
Věci se stávají složitějšími, ale chceme, aby naše skripty přijaly určitá rozhodnutí, aby udělaly to či ono. Měl jsem se zabývat jinými tématy, ale tento článek o kontrolních strukturách bash se příliš rozrostl.
Na dalších se budu věnovat potrubí a přesměrování. Pravděpodobně se vrátím k těmto řídicím strukturám bash s příklady, něco jako použití výstupu příkazu ve smyčce for-in a podobně.