C2110 Operační systém UNIX základy programování 8. lekce bash - dokončení (skoro) Petr Kulhánek, Jakub Štěpán kulhanek@chemi.muni.cz Národní centrum pro výzkum biomolekul, Přírodovědecká fakulta Masarykova univerzita, Kamenice 5, CZ-62500 Brno perační systém UNIX a základy programování 8. lekce Domácí úkoly Pokyny: 1. Uvedené úkoly jsou pro pokročilé studenty. 2. Cílem úkolů je rozvinout vaši schopnost řešit problémy, který jsou zdánlivě neřešitelné z pohledu možností a zdrojů, které máte k dispozici. V případě jazyka bash se jedná převážně o možnost pracovat pouze s celočíselnou aritmetikou a omezený způsob vykreslování na terminál. Zadání: 1. Vykreslete kruh z písmen "X". Poloměr kruhu zadá uživatel po spuštění skriptu. 2. Vykreslete kružnici z písmen "X". Poloměr kružnice zadá uživatel jako první argument skriptu. perační systém UNIX a základy programování 8. lekce -2- Obsah > Příkaz test porovnávání celých čísel a řetězců > Cyklus • for vs while, for in, přesměrování a roury perační systém UNIX a základy programování 8. lekce [ Příkaz test; celá čísla Příkaz test slouží k porovnávání hodnot a testovaní typů souborů a adresářů (man bash, man test). V případě, že je test splněn, je návratová hodnota příkazu nastavena na 0 (pravda). Porovnávání celých čísel: test cislol operator cislo2 Operátor: -eq rovná se (equal) -ne nerovná se (not equal) -It menši než (less than) -le menši než nebo rovno (less or equal) -gt větši než (greater than) -ge větši než nebo rovno (greater or equal) Alternativní zápis: ___ [[ cislol operator cislo2 ]] musí být mezery Příkaz test, řetězce Porovnávam retezcu test retezecl operátor retezec2 [[ retezecl operátor retezec2 ]] Operátor: == řetězce jsou identické (lze použit i =) != řetězce se liši Testovaní řetězců test operátor retezecl [[operátor retezecl ]] Operátor: -n testuje zda-li řetězec nemá nulovou délku -z testuje zda-li řetězec má nulovou délku -f testuje zda-li je řetězec název existujícího souboru -d testuje zda-li je řetězec název existujícího adresáře Dperační systém UNIX a základy programování 8. lekce Příkaz test, logické operátory Logické operátory: | | logické nebo && logické ano ! negace • Pomocí logických operátorů, lze vytvářet složitější podmínky. • Pokud neznáme prioritu operátorů nebo si nejsme jisti, tak používáme kulaté závorky. • Bash používá líné vyhodnocování podmínek, které spočívá ve vyhodnocování pouze té části složené logické podmínky, kterou je nutné vyhodnotit pro zjištění výsledné logické hodnoty. perační systém UNIX a základy programování 8. lekce [ Příkaz test; příklady [[ (I -ge 5) && (I -le 10) ] ] Je hodnota proměnné I v intervalu <5;10>? [[ (I -lt 5)||(I -gt 10) ]] nebo [[ !((I -ge 5)&&(I -le 10)) ]] Je hodnota proměnné I mimo interval <5;10>? [ [ I -ne 0 ]] Je hodnota proměnné I menši nebo rovna nule? [[ "$A" == "test" ]] Obsahuje proměnná A řetězec "test"? [[ "$A" != "test" ]] Obsahuje proměnná A jiný řetězec než "test"? [ [ -z "$A" ] ] Obsahuje proměnná A prázdný řetězec? [[ -f "$NAME" ]] Existuje soubor, jehož jméno je v proměnné NAME? [ [ ! (-d "$NAME") ] ] Neexistuje adresář, jehož jméno je v proměnné NAME? perační systém UNIX a základy programování 8. lekce -7- Cvičení 1. Napište skript, který se uživatele postupně zeptá na dvě čísla. Po jejich zadání vypíše jejich podíl. Ve skriptu ošetřete možnou chybu při dělení nulou. 2. Napište skript, který vytvoří adresář, jehož jméno zadá uživatel po spuštění skriptu. Ošetřete chybovou situaci způsobenou tím, že vytvářený adresář již existuje. 3. Napište skript, který se dotáže na celé číslo. Skript pak otestuje, zda-li se skutečně jedná o celé číslo. perační systém UNIX a základy programování 8. lekce -8- Cyklus pomocí for Cyklus (smyčka) je řídicí struktura, která opakovaně provádí posloupnost příkazů. Opakování i ukončení cyklu je řízeno podmínkou. pokud je podmínka splněna, vykonají se příkazy prikazl a další provede se před spuštěním cyklu (inicializace počítadla) for((inicializace;podminka;zmena)) do prikazl • • • done Kompaktní zápis: for((inicializace;podminka;zmena)); do prikazl • • • done aktualizace počítadla po vykonání příkazů perační systém UNIX a základy programování 8. lekce Cyklus pomocí for a vývojový diagran for((I = 0; I < N; I = I + 1)); do echo $1 done perační systém UNIX a základy programování 8. lekce -10- Cyklus pomocí for versus while provede se před spustením cyklu (inicializace počítadla) Kromě změny počítadla na konci cyklu, je možné provádět i další změny v těle cyklu. Toto se však NEDOPORUČUJE, protože to snižuje čitelnost kódu. pokud je podmínka splněna, vykonají se příkazy v bloku do/done ►1=1 while [[ $1 -le 10 ] ] ; do echo $1 ((1=1+ 1 )) done aktualizace počítadla po vykonání příkazů Změnu počítadla je možné provádět kdekoliv v těle cyklu (i na více místech). perační systém UNIX a základy programování 8. lekce Cyklus pomocí for, použití Vypíše čísla 1 až 10 Vypíše čísla 10 až 1 for((I=l;I <= 10;I++)); do for((1=10;I >= 1;I—)); do echo $1 echo $1 done done Proměnná I má roli počítadla. Inicializace se řídí volnými pravidly, jelikož je Podmínka: Lze použít následující porovnávací operátory: výraz uveden v (()) bloku. i = nerovná se ! == rovná se Změna: i < menší Lze použít libovolný výraz, který je možné ! <= menší nebo rovno interpretovat v (()) bloku, např. i > vetsi ++ hodnotu proměnné zvýší o jedničku — hodnotu proměnné sníží o jedničku ! >= větší nebo rovno další.... Lze použít pouze na celá čísla v (()) perační systém UNIX a základy programování 8. lekce Cyklus pomocí for, změna počítadla Pokud lze proměnnou interpretovat jako celé číslo, lze použít následující aritmetické operátory: ++ hodnotu proměnné zvýší o jedničku A++ hodnotu proměnné sníží o jedničku A— + sečte dvě hodnoty A = 5 + 6 A = A + 1 odečte dvě hodnoty A = 5 - 6 A = A - 1 * vynásobí dvě hodnoty A = 5 * 6 A = A * 1 / vydělí dvě hodnoty (celočíselné dělení) A = 5 / 6 A = A / 1 A=A+3 += k proměnné přičte hodnotu A += 3 A += B -= od proměnné odečte hodnotu A -= 3 A -= B *= proměnnou vynásobí hodnotou A *= 3 A *= B /= proměnnou podělí hodnotou A/=3 A/= B perační systém UNIX a základy programování 8. lekce Vnořování cyklů Řídící skupiny cyklů lze do sebe libovolně vnořovat. ^ vnější cyklus for((1=1;I <= 10;!++)); do_ for((J=l;J<= 10;J++)); do echo "$I $J" done done počítadlo vnějšího cyklu může ovlivňovat chování vnitřního cyklu for((I=l;I <= 10;!++)); for((J=l;J<= do echo "$I $J" Počet vnoření není omezen. Lze done kombinovat s jinými cykly (while, done until, for in) nebo podmínkami. )perační systém UNIX a základy programování 8. lekce vnitřní cyklus Cvičení 1. Napište skripty v jazyce bash pro Úkol 1 a 2, místo cyklu pomocí while použijte cyklus pomocí for. Rozměr vykreslovaného obrazce nechť uživatel zadá jako první argument skriptu. Skript otestuje, zda-li je zadán správný počet argumentů a zda-li je první argument celé číslo větší než nula. perační systém UNIX a základy programování 8. lekce Do terminálu vytiskněte čtverec se znaků X. Délku strany čtverce zadá uživatel. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X To, že se nejedná vzhledově o čtverec, ignorujte. Počet znaků X na řádku a počet řádků však musí být stejný. perační systém UNIX a základy programování 8. lekce -16- Úkol 2 Do terminálu vytiskněte pravoúhlý trojúhelník se znaků X, tak aby jedna odvěsna byla umístěna nahoře a druhá na levé straně. Délku odvěsny zadá uživatel. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X perační systém UNIX a základy programování 8. lekce [ Cyklus pomocí for... in ... Příkazy v bloku do/done (prikazl,...) se vykonají pro každý prvek v seznamu LIST. V daném běhu cyklu obsahuje proměnná VAR aktuální prvek ze seznamu LIST. for VAR in LIST do prikazl $VAR done • • • Kompaktní zápis: for VAR in LIST; do prikazl $VAR • • • done perační systém UNIX a základy programování 8. lekce -18- Cyklus pomocí for... in seznamy for A in a b c; do echo $A done Cyklus proběhne třikrát, během toho postupně vytiskne znaky a, b, c. Seznamy položek je vhodné vytvářet programově (pomocí příkazů uvedených v obrácených apostrofech). for A in xls *.epsx; do ./process_file $A done Příkaz process_file se vykoná pro každý soubor s příponou .eps, který se nachází v aktuálním adresáři. for A in x seq 1 0.25 10x; do printf "%8 .3f\n " $A done Vypíše reálná čísla v intervalu od 1 do 10 s přírůstkem 0,25. Čísla budou uvedeny s přesností tří desetinných míst a zarovnány doprava v poli o délce 8 znaků. Dokumentace: man seq )perační systém UNIX a základy programování 8. lekce Presmerovania roury Čtení souboru po řádcích: cat soubor.txt | while read A; do prikaz2 • • • done roura while read A; do prikaz2 • • • done < soubor. txt Přesměrování do souboru: for((1=1;I <= 10;I++)); do echo $1 done > soubor.txt presmerovaní Výstup všech příkazů v cyklu je přesměrován do soubor.txt. perační systém UNIX a základy programování 8. lekce Přesměrování a roury - příklady for((I=l;I <= 10;I++)); do echo $1 done > soubor.txt for((I=l;I <= 10;I++)); do echo $1 printf "N=%10d\n" $1 done > soubor.txt stejná funkcionalita rm -f soubor.txt for((I=l;I <= 10;I++)); do echo $1 » soubor.txt done rozdílná funkcionalita rm -f soubor . txt for((1=1;I <= = 10;I++)); do echo $1 » soubor. txt printf "N=%10d\n" $1 done perační systém UNIX a základy programování 8. lekce Cvičení 1. Upravte skripty z předchozího cvičení, tak aby se rozměr obrazce načítal ze standardního vstupu a výsledný obrazec se tisknul do souboru, jehož jméno zadá uživatel opět ze standardního vstupu. 2. Napište skript, který vypíše reálná čísla v intervalu od -10 do 10 s přírůstkem 0,5. Čísla budou uvedena včetně znaménka, zarovnány doprava v poli 10 znaků a uvedeny s přesností na jedno desetinné místo. perační systém UNIX a základy programování 8. lekce -22- Domácí úkoly perační systém UNIX a základy programování 8. lekce Domácí úkol I Vysvětlete rozdílné chování následujících skriptů. Soubor data.txt obsahuje pět řádků. #!/bin/bash 1 = 0 cat data.txt | while read A; do I=$( ($1 + 1) ) done vypíše číslo 0 #!/bin/bash 1 = 0 while read A; do I=$( ($I + D ) done < data.txt echo $1 ----- výpise cislo 5 perační systém UNIX a základy programování 8. lekce Domácí úkol II Soubor rst.out (wolf.ncbr.munixz:/home/kulhanek/Documents/C2110/Lesson08/rst.out) obsahuje výsledky z molekulové dynamiky. Úkolem je ze souboru vyextrahovat závislost teploty simulovaného systému na čase a tyto data uložit do souboru temp.out, který bude obsahovat právě dva sloupce. První sloupec bude čas a druhý sloupec bude teplota. cas teplota NSTEP = Etot BOND 1-4 NB = EELEC = 500 TIME(PS) = 0.500 TEMP(K) = 288.02 PRESS = 942.6248 51.3204 17.7099 -494 .7423 EKtot ANGLE 1-4 EEL EGB 151.0990 292.3619 981.4071 -164.7991 EPtot DIHED VDWAALS RESTRAINT 0.0 791.5258 176.5980 -68.3301 0.1822 EAMBER (non-restraint) 791.3436 POZOR: Skript nesmí obsahovat příkazy grep, awk a ani jejich varianty. Při řešení použijte příkaz read a while. perační systém UNIX a základy programování 8. lekce Samostudium Funkce - pro pokročilé studenty. perační systém UNIX a základy programování 8. lekce Funkce - definice Funkce je konstrukce, která umožňuje seskupit část kódu tak, aby jej bylo možné snadno použít na více místech skriptu. Funkce tedy usnadňuje a zpřehledňuje zápis opakovaných úkonů. Definice: function jméno () { prikazl prikaz2 } function jméno { prikazl prikaz2 } jméno () { prikazl prikaz2 } alternativní zápisy Argumenty funkce se nedeklaruje nedochází tedy k žádné kontrole v počtu argumentů, typové kontrole, funkce nelze přetěžovat. Zadané argumenty jsou dostupné přes speciální proměnné #, 1 až 9, *. Funkce se volají jako existující příkaz. Proměnné ve funkci jsou globální (lze změnit pomocí klíčového slova local). Dokumentace: man bash, sekce FUNCTIONS. perační systém UNIX a základy programování 8. lekce Funkce - použití # print line - the length is in the first argument function print line () { N=$l * for((*=l;J <= N;J++)); do eVho -n " X" done \ echo "" \ # use function \ print line 10 # jorint line 10 characters long print line 5^V# pVint line 5 characters long hodnota argumentu je dostupná ve speciální proměnné 1 perační systém UNIX a základy programování 8. lekce [cvičení 1. Napište jeden skript, který vytiskne čtverec a trojúhelník (podobně jako v úkolu 1 a 2) pro jednu zadanou délku za sebe do terminálu. Ve skriptu identifikujte část, která se opakuje a přepište ji za použití funkce. X X X X X X X X X X X X X X X X X X X X XXX X X X To, že se nejedná vzhledově o čtverec, ignorujte. Počet znaků X na řádku a počet řádků však musí být stejný. perační systém UNIX a základy programování 8. lekce -29-