C2110 Operační systém UNIX a základy programování 9. lekce bash - dokončení (skoro) 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 Operační systém UNIX a základy programování 9. 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. Dperační systém UNIX a základy programování 9. lekce 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 Dperační systém UNIX a základy programování 9. 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 -ne -lt -le -gt -ge rovná se (equal) nerovná se (not equal) menši než (less than) menši než nebo rovno (less or equal) větši než (greater than) větši než nebo rovno (greater or equal) Alternativní zápis: [[ öi< musí být mezery operator ]] Dperační systém UNIX a základy programování 9. lekce __u Příkaz test, řetězce Porovnávání řetězců 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 Operační systém UNIX a základy programování 9. 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. Dperační systém UNIX a základy programování 9. lekce -6- 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 různá od nuly? [[ "$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? Dperační systém UNIX a základy programování 9. lekce Cvičení I 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. Dperační systém UNIX a základy programování 9. 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ů Dperační systém UNIX a základy programování 9. lekce Cyklus pomocí for a vývojový diagram for((I = 0; I < N; I = I + 1)); do echo $1 done Dperační systém UNIX a základy programování 9. lekce -10- Cyklus pomocí for versus while provede se před spužtění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). Dperační systém UNIX a základy programování 9. 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. t = nerovná se 1 == rovná se Změna: j < menší Lze použít libovolný výraz, který je možné 1 <= menší nebo rovno interpretovat v (()) bloku, např. j > vetsi ++ hodnotu proměnné zvýší o jedničku — hodnotu proměnné sníží o jedničku >= L —— —- větší nebo rovno další.... Lze použít pouze na celá čísla v (()) Dperační systém UNIX a základy programování 9. lekce Cyklus pomocí for, změna počítad 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 Dperační systém UNIX a základy programování 9. lekce Vnořování cyklů Řídící skupiny cyklů lze do sebe libovolně vnořovat. vnější cyklus for((I=l;I <= 10;!++)); do * for((J=l;J<= 10;J++)); do echo "$I $J" done done for((I=l;I <= 10;!++)); for((J=l;J <= ) ; do echo "$I $J" done done vnitřní cyklus počítadlo vnějšího cyklu může ovlivňovat chování vnitřního cyklu Počet vnoření není omezen. Lze kombinovat s jinými cykly (while, until, for in) nebo podmínkami. Dperační systém UNIX a základy programování 9. lekce Cvičení II 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. 2. Upravte řešení Úkolu 1 tak, aby se vykresloval obdélník. Rozměry obdélníku bude uživatel zadávat interaktivně po spuštění skriptu. Dperační systém UNIX a základy programování 9. lekce -15- Úkol 1 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ý. Dperační systém UNIX a základy programování 9. lekce Ú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 Dperační systém UNIX a základy programování 9. 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 $YAR done • • • Kompaktní zápis: for VAR in LIST; do prikazl $VAR • • • done Dperační systém UNIX a základy programování 9. lekce -18- Cyklus pomocí for... in seznam 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 Dperační systém UNIX a základy programování 9. 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. Dperační systém UNIX a základy programování 9. 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 Dperační systém UNIX a základy programování 9. lekce Cvičení III 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. Dperační systém UNIX a základy programování 9. lekce -22- Domácí úkoly Dperační systém UNIX a základy programování 9. 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 Dperační systém UNIX a základy programování 9. lekce Domácí úkol II Soubor rst.out (wolf.ncbr.munixz:/home/kulhanek/Documents/C2110/Lesson09/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 NSTEP = Etot BOND 1-4 NB = EELEC = 500 TIME (PS) 942.6248 51.3204 17.7099 -494 .7423 EKtot ANGLE 1-4 EEL EGB 0.500 TEMP(K) 151.0990 292.3619 981. 4071 -164.7991 EAMBER (non-restraint) 791.3436 teplota 288.02 PRESS EPtot DIHED VDWAALS RESTRAINT 0.0 791.5258 176.5980 -68.3301 0.1822 POZOR: Skript nesmí obsahovat příkazy grep, awk a ani jejich varianty. Při řešení použijte příkaz read a while. Dperační systém UNIX a základy programování 9. lekce Samostudium Funkce - pro pokročilé studenty. Dperační systém UNIX a základy programování 9. 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: jméno () { prikazl prikaz2 • • • 7^ isy 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. function jméno () { prikazl prikaz2 } function jméno { prikazl prikaz2 } alternativní zát Dperační systém UNIX a základy programování 9. lekce -27- Funkce - použití # print line - the length is in the first argument function print line () { N=$l for((*=l;J <= N;J++)); do e\ho -n " X" done \ echo "" \ # use function \ print line 10 # Rrint line 10 characters long print line 5^v # pVint line 5 characters long hodnota argumentu je dostupná ve speciální proměnné 1 Dperační systém UNIX a základy programování 9. lekce -28- 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ý. Dperační systém UNIX a základy programování 9. lekce