C2110 Operační systém UNIX a základy programování 7. lekce -1C2110 Operační systém UNIX a základy programování Petr Kulhánek kulhanek@chemi.muni.cz Národní centrum pro výzkum biomolekul, Přírodovědecká fakulta Masarykova univerzita, Kamenice 5, CZ-62500 Brno 7. lekce Skriptování v jazyce bash C2110 Operační systém UNIX a základy programování 7. lekce -2- Obsah  Skriptování v bashi • základní syntaxe, srovnání s vývojovými diagramy, spouštění skriptů  Proměnné • nastavení a získaní hodnoty, proměnné a procesy, interpretace řetězců  Vstup a výstup • read, echo, printf  Aritmetické operace • operace s celými čísly C2110 Operační systém UNIX a základy programování 7. lekce -3Skriptování v bashi C2110 Operační systém UNIX a základy programování 7. lekce -4Skript v Bashi #!/bin/bash # toto je komentar echo 'Toto je skript v interpretu Bash!' echo "Obsah adresare `pwd` je:" ls # vypise obsah adresare A=6 # nastaveni hodnoty promenne A echo "Hodnota promenne A je $A" echo "jeden prikaz"; echo "druhy prikaz" ./mujprikaz prvni_argument druhy_argument \ treti_argument pořadívykonávánípříkazů • prázdné řádky se ignorují • text uvozený znakem # se ignoruje (používá se ke komentovaní funkčnosti skriptu) • na jeden řádek lze uvést více příkazů, příkazy se oddělují středníkem ; • jeden příkaz lze napsat na více řádků pomocí zpětného lomítka \ ihned následuje nový řádek C2110 Operační systém UNIX a základy programování 7. lekce -5V čem psát skripty (a programy) Jelikož jsou skripty a zdrojové kódy programů textové soubory, lze použít libovolný textový editor umožňující uložení textu v čisté formě (bez formátovacích metadat). Textové editory:  vi  kwrite  kate  gedit K psaní skriptů a zdrojových kódů programů lze používat i specializované vývojové prostředí – IDE (Integrated Development Enviroment). IDE obsahuje kromě editoru i správce projektu, ladící nástroje (debugger) a další. Většinou dostupné pro komplexnější jazyky: C, C++, Fortran, JavaScript, Python, PHP, atd. Vývojové prostředí:  Kdevelop  qtcreator  NetBeans  Eclipse C2110 Operační systém UNIX a základy programování 7. lekce -6Vývojový diagram a skript v bashi Z K #!/bin/bash echo 'Toto je skript v interpretu bash!' echo "Obsah adresare je:" ls exec ls pořadí vykonávání příkazů writestr 'Toto je skript v interpretu bash!' writestr "Obsah adresare je:" C2110 Operační systém UNIX a základy programování 7. lekce -7Spouštění skriptů 1) Nepřímé spouštění Spouštíme interpreter jazyka a jako argument uvádíme jméno skriptu. $ bash muj_skript_v_bashi Skripty nemusí mít nastaven příznak x (executable). 2) Přímé spouštění Spouštíme přímo skript (shell automaticky spustí interpreter). $ chmod u+x muj_skript_v_bashi $./muj_skript_v_bashi Skripty musí mít nastaven příznak x (executable) a interpreter (součást skriptu). #!/bin/bash echo 'Toto je skript v interpretu Bash!' C2110 Operační systém UNIX a základy programování 7. lekce -8Určení interpretru #!/bin/bash echo "Toto je skript v bashi!" Skript v bashi #!/absolutní/cesta/k/interpretru/skriptu Specifikace interpretru (první řádek skriptu):  Pokud není interpreter skriptu při jeho přímém spuštění uveden, použije se interpreter systémového shellu (bash).  Interpreter uvedený ve skriptu se ignoruje při nepřímém spuštění.  Interpretr je vhodné do skriptu vždy uvádět, protože je použit textovými editory pro zvýrazňování syntaxe. (Název souboru uvádíme bez přípony, popř. s příponou .sh) #!/usr/bin/gnuplot set xrange[0:6] plot sin(x) pause -1 Skript v gnuplotu C2110 Operační systém UNIX a základy programování 7. lekce -9Cvičení I 1. Napište skript v jazyce bash, který vypíše text "Aktualni adresar je:" následovaný výpisem absolutní cesty k aktuálnímu adresáři. Skript spusťte nepřímo pomocí interpretu bash. 2. Rozšiřte funkčnost předchozího skriptu tak, aby kromě výše uvedeného vypsal "Obsah adresare je:" následovaný výpisem seznamu souborů a adresářů v dlouhém formátu. Skript spusťte přímo. C2110 Operační systém UNIX a základy programování 7. lekce -10- Proměnné C2110 Operační systém UNIX a základy programování 7. lekce -11- Proměnné V jazyce Bash se proměnnou rozumí pojmenované umístění v paměti, které obsahuje hodnotu. Hodnota proměnné v jazyce Bash je vždy typu řetězec (text). Nastavení proměnné: $ JMENO_PROMENNE=hodnota $ JMENO_PROMENNE="hodnota s mezerami" Přístup k hodnotě proměnné: $ echo $JMENO_PROMENNE Zrušení proměnné: $ unset JMENO_PROMENNE Přehled všech definovaných proměnných: $ set nesmí být mezera mezi jménem proměnné a = "TEXT ${PROMENNA}TEXT" pokud má být hodnota součásti textu, tak se název proměnné uvádí do složených závorek C2110 Operační systém UNIX a základy programování 7. lekce -12Nastavení proměnné $ JMENO_PROMENNE="hodnota s mezerami" $ JMENO_PROMENNE ="hodnota s mezerami" $ JMENO_PROMENNE= "hodnota s mezerami" $ JMENO_PROMENNE="hodnota s mezerami" program [arg1...] interpretuje se jako název programu mezera interpretuje se jako argument programu mezera interpretuje se jako název programuJMENO_PROMENNE se nastaví na prázdný řetězec, hodnota proměnná je dostupná pouze spouštěnému programu lze uvést několik proměnných a jejich hodnot (v zápisu se dvojice JMÉNO=HODNOTA oddělují mezerou), které jsou dostupné jen pro spuštěný program pokud název programu obsahuje rovnítko, musí být název uveden v uvozovkách C2110 Operační systém UNIX a základy programování 7. lekce -13- Řetězce V jazyce Bash lze použít čtyři typy řetězců: • bez uvozovek A=pokus B=* C=$A • s uvozovkami A="pokus hokus" B="* $A" • s jednoduchými uvozovkami (apostrof) A='pokus hokus' B='* $A' • s obrácenými jednoduchými uvozovkami (obrácený apostrof) A=`ls –d` B="pocet : `ls | wc –l`" nedojde k expanzi, protože se divoký znak nevyskytuje ve slově, které by bylo možné expandovat nahradí se hodnotou proměnné A nahradí se hodnotou proměnné A, hvězdička se neexpanduje (je uvedena v uvozovkách) text je uveden přesně, bez žádné expanze či transformace hodnota proměnně obsahuje dvě slova oddělené mezerou do místa obrácených uvozovek se vloží výstup příkazu uvedeného v uvozovkách C2110 Operační systém UNIX a základy programování 7. lekce -14Expanze řetězce/příkazové řádky Pořadí expanze řetězce/příkazové řádky: vstupní text (řetězec) expanze proměnných mezivýsledek expanze speciálních znaků (wildcards) výsledek expanze se neprovede, pokud je text uveden ve standardních uvozovkách ("), nebo není obsažen ve slově, které by bylo možné expandovat, netýká se tedy přiřazení hodnoty do proměnných expanze se neprovede, pokud je text uveden v jednoduchých uvozovkách (') C2110 Operační systém UNIX a základy programování 7. lekce -15- Procesy Proměnné Proces: pid, ppid Proces: pid, ppid Proměnné rodičovský proces dceřiný proces • Prvním spuštěným procesem po spuštění systému je proces “init” • Každý příkaz spuštěný v shellu (příkazové řádce) je procesem pid = identifikátor procesu ppid = identifikátor rodičovského procesu Proces je instance běžícího programu. paměť vyhrazená pro proměnné C2110 Operační systém UNIX a základy programování 7. lekce -16Proměnné a procesy Proměnné Proces: pid, ppid Proces: pid, ppid Proměnné rodičovský proces dceřiný proces Každý proces má vyhrazenou část pro ukládání hodnot proměnných. Dceřiný proces v okamžiku svého spuštění získá kopii proměnných (exportovaných) a jejich hodnot od rodičovského procesu. Tyto proměnné může dle potřeby měnit nebo mazat. Dále může nastavovat nebo mazat nové proměnné. Všechny tyto změny však po skončení dceřiného procesu zaniknou. Změny se neprojeví na hodnotách původních proměnných rodičovského procesu. Export proměnné: $ export JMENO_PROMENNE $ export JMENO_PROMENNE="hodnota" export export s přiřazením C2110 Operační systém UNIX a základy programování 7. lekce -17Cvičení II 1. Nastavte proměnnou A na hodnotu 55. 2. Vypište hodnotu proměnné A (příkazem echo) 3. Vylistujte všechny proměnné nastavené v daném terminálu. Je mezi nimi proměnná A? Použijte příkaz less nebo more k zpřehlednění výpisu. 4. Použijte příkaz grep a vypište pouze řádek obsahující záznam o proměnné A. Vyhledávací vzor zvolte tak, aby byl nezávislý na hodnotě proměnné. 5. Vypište všechny nastavené proměnné, jejichž jména začínají písmenem A (grep ^TEXT). 6. Změňte hodnotu proměnné na "tohle je dlouhy retezec". 7. Vypište hodnotu proměnné A. 8. Zrušte proměnnou A. 9. Ověřte, že jste proměnnou zrušili (postupem řešeným v bodě 4). 10. Postupně nastavujte proměnné A, B a C podle příkladů uvedených na straně 15. Postupně ověřujte jejich hodnotu příkazy set a echo. Analyzujte případné rozpory. Pracujte v interaktivním režimu shellu. C2110 Operační systém UNIX a základy programování 7. lekce -18Cvičení III $ ./print_C $ C="hodnota 1" ./print_C $ echo $C $ C="hodnota 2" $ echo $C $ ./print_C $ export C $ ./print_C 1. Zrušte proměnnou PATH. Jak se změna projeví na funkcionalitě příkazové řádky? Zkuste spustit příkaz ls a pwd. Chovaní vysvětlete. 2. Kdy se provede expanze divokého znaku * v následujícím příkladu: 3. Napište skript s názvem print_C, který vypíše hodnotu proměnné C. Vysvětlete chování v následujících příkladech: $ B="Obsah adresare je *" $ echo $B Pracujte v novém terminálu. C2110 Operační systém UNIX a základy programování 7. lekce -19- Vstup/výstup C2110 Operační systém UNIX a základy programování 7. lekce -20Příkaz read Příkaz read slouží k čtení textu ze standardního vstupu (tj. pro interaktivní načítaní vstupu) a jeho uložení do proměnných. Příkaz načte vždy celý řádek, do první proměnné se uloží první slovo, ..., do poslední proměnné se uloží zbytek řádku. Syntaxe: read A # celý řádek se uloží do proměnné A read A B # první slovo se uloží do proměnné A # zbytek řádku do proměnné B Příklad: echo -n "Zadej hodnotu: " read A echo "Zadana hodnota je : $A" Pozor: nepoužívejte přikaz read ve spojení s rourami echo "text" | read A echo $A Nebude obsahovat hodnotu "text" C2110 Operační systém UNIX a základy programování 7. lekce -21Argumenty skriptu $ bash muj_skript_v_bashi arg1 arg2 arg3 $./muj_skript_v_bashi arg1 arg2 arg3 #!/bin/bash echo "Pocet zadanych argumentu: $#" echo "Prvni argument je: $1" echo "Druhy argument je: $2" echo "Vsechny zadane argumenty jsou: $*" echo "Nazev spusteneho skriptu: $0" 3 arg1 arg2 arg1 arg2 arg3 Použití a význam argumentů si určuje autor skriptu. ./muj_skript_v_bashi C2110 Operační systém UNIX a základy programování 7. lekce -22Argumenty skriptu - proměnné Argumenty skriptu (názvy speciálních proměnných): # počet argumentů, se kterými byl skript spuštěn 0 název spuštěného skriptu 1 … 9 hodnoty argumentů 1 až 9, se kterými byl skript spuštěn * všechny argumenty, se kterými byl skript spuštěn Pokud potřebujeme předat více jak devět argumentů, je nutné použít příkaz shift. Příkaz odstraní první argument ze seznamu argumentů. for((I=1;I <= $#;I++)); do echo $1 shift done Pokročilá práce s argumenty: Vypíše postupně zadané argumenty skriptu. C2110 Operační systém UNIX a základy programování 7. lekce -23Cvičení IV 1. Napište skript, který se dotáže uživatele na jeho oblíbenou barvu, kterou posléze vypíše na terminál. 2. Napište skript, který vypíše počet zadaných argumentů a hodnotu prvního argumentu. C2110 Operační systém UNIX a základy programování 7. lekce -24Příkaz echo Příkaz echo slouží k neformátovanému výpisu do standardního výstupního proudu. Příkaz tiskne řetězce v zadaném pořadí oddělené mezerou. Syntaxe: echo [volby] [retezec1] [retezec2] ... Užitečné volby: -n neodřádkuje výstup Příklady: $ echo "Ema" "mele" "maso." Ema mele maso. $ echo "Ema mele maso." Ema mele maso. $ echo –n "Zadejte barvu: " $ A=5 $ echo "Hodnota promenne A je $A." Hodnota promenne A je 5. C2110 Operační systém UNIX a základy programování 7. lekce -25Příkaz printf Syntaxe: printf [format] [hodnota1] [hodnota2] ... "Cislo %5d ma hodnotu %03d" do tohoto místa vlož hodnotu1 v daném formátu Příkaz printf slouží k vypisování formátovaných textů a čísel. do tohoto místa vlož hodnotu2 v daném formátu C2110 Operační systém UNIX a základy programování 7. lekce -26Příkaz printf, příklady $ I=10 $ B=12.345 $ printf "Hodnota promenne I je %d\n" $I Hodnota promenne I je 10 $ printf "Zadane cislo B je %10.4f\n" $B Zadane cislo B je 12.3450 $ printf "Zadane cislo B je %010.4f\n" $B Zadane cislo B je 00012.3450 $ printf "Zadane cislo B je %+010.4f\n" $B Zadane cislo B je +0012.3450 $ printf "Cislo I je %-5d a cislo B je %.1f\n" $I $B Cislo I je 10 a cislo B je 12.3 C2110 Operační systém UNIX a základy programování 7. lekce -27Příkaz printf, formát Další informace: man bash, man printf %[priznak][delka][.presnost]typ celková délka pole počet míst za desetinou tečkou (reálná čísla) Příznak: - zarovnat doleva 0 prázdné místo zaplnit nulami + vždy uvést znaménko Typ: d celé číslo s řetezec (text) f reálné číslo Speciální znaky: \n konec řádku \r vrať se na začátek řádku %% znak % [] – volitelná část C2110 Operační systém UNIX a základy programování 7. lekce -28Cvičení V 1. Napište skript, který se dotáže uživatele na jeho oblíbenou barvu, kterou posléze vypíše na terminál. Dotaz vytiskněte tak, aby zadávaná barva byla na stejném řádku jako dotaz. 2. Procvičte si příkaz printf tak, že provedete příkazy uvedené v příkladech. 3. Napište skript, který vypíše první zadaný argument skriptu ve formátu %4d. 4. Napište skript, který načte ze standardního vstupu číslo a to vypíše následujícím způsobem: bude uvedeno znaménko, pro výpis se použije pět míst, prázdné místa budou vyplněny nulami: Zadane cislo je : +0003 5. Co se stane, pokud skriptu ze cvičení 4, předložíte číslo: 123456? C2110 Operační systém UNIX a základy programování 7. lekce -29Domácí úkoly C2110 Operační systém UNIX a základy programování 7. lekce -30Aritmetické operace C2110 Operační systém UNIX a základy programování 7. lekce -31Aritmetické operace Aritmetické operace s celými čísly lze vykonat v bloku (( ... )). Možné zápisy: (( I = I + 1 )) (( I++ )) I=$(( I + 1 )) echo "Hodnota I zvetsena o jedna : $(( I + 1 ))" Operátory: = přiřazení + sčítání - odčítání * násobení / dělení % zbytek po dělení ++ inkrementace (zvýšení hodnoty o 1) –- dekrementace (snížení hodnoty o 1) Další informace: man bash hodnotu výsledku vypíše do místa zápisu C2110 Operační systém UNIX a základy programování 7. lekce -32Příkaz expr Příkaz expr vyhodnocuje matematické výrazy, výsledky se tisknou do standardního výstupu. Další informace: man expr Příklady: $ expr 1 + 2 3 $ expr 2 \* 3 6 I=`expr $I + 1` výsledek vložíme do proměnné I \ zabrání expanzi speciálního znaku * na jména souborů a adresářů nacházejících se v aktuálním adresáři předáváme hodnotu proměnné Další možností je použití příkazu bc, který umí pracovat i s reálnými čísly. C2110 Operační systém UNIX a základy programování 7. lekce -33Domácí úkol 1. Napište skript, kterému se budou předkládat dvě čísla jako argumenty. Skript tyto čísla vypíše a dále vypíše jejich součet. 2. Napište skript, který se uživatele postupně zeptá na dvě čísla. Po jejich zadání vypíše jejich součin.