Coding in BASH #5

07.01.2008 12:21 | blackhole_socket

Ďalšie pokračovanie tohto seriálu o bashi je na svete. V dnešnej časti si čo-to povieme o užívatelskom vstupe do bash scriptov a o funkciách AND a OR. Tak poďme na to.


Užívateľský vstup do bash scriptov

Teraz konečne prichádza nejaká zábavná část. V bashi môžete vytvoriť program, ktorý bude interaktívny, teda bude reagovať na vstup užívateľa (prípad. na vstup čítaný zo súboru). Príkaz uživateľského vstupu je príkaz read. Jedná sa o vnútorný príkaz shellu. Príkaz vyžaduje ako parameter premennú. Teraz si uvedieme jednoduchý príklad:

#!/bin/bash
echo -n "Zadaj svoj nick: "
read meno
echo "Vitaj v systeme $meno!"

Script počká, až napíšete váš nick a stisnete klávesu ENTER. Potom sa to, čo ste napísali uloží ako hodnota do premennej meno. Ta sa potom môže ďalej v programe využívať rovnako ako akákoľvek iná premenná. Využitie hodnoty ktorá už nemusí byť zadaná uvádza nasledujúci príklad:

#!/bin/bash
echo -n "Zadaj svoj nick: "
read meno
if [ -z "$meno" ]; then
  echo "Ty si mi nepovedal svoj nick!"
  exit
fi
echo "Zdravím ta $meno!"

Toto je typický príklad kontroly vstupných dát. Nemôžeme totiž predpokladať, že užívateľ vždy zadá to, čo očakávame a je teda nutné sa proti tomu brániť. Je však vhodné užívateľa na zle zadané dáta upozorňovať citľivo a nie tak, aby si užívateľ z toho vydedukoval, že si o ňom myslíme, že je lama. Pokiaľ užívateľ nezadá žiadne meno (nick ), bude podmienka vyhodnotená ako true, vypíše sa chybová hláška a script sa ukončí.


AND a OR v bash scriptoch

Videli sme už štruktúry, ktoré riešili podmienky, ale podmienky môžeme eště viacej zdokonaliť. Pokiaľ chceme napríklad, aby pre vykonanie následujúceho príkazu boli splnené dve alebo viac podmienok naraz, alebo aby bola splnená aspoň niektorá z niekoľkých podmienok, použijeme práve znaky || nebo && medzi jednotlivými podmienkami. Znaky || znamenajú alebo (OR, logický súčet). Pokiaľ je aspoň jedna z podmienok oddelených tymito znakmi true, je výsledok true. Naopak znaky && znamenajú a (AND, logický súčin). Tu musia byť splnené všetky podmienky, aby výsledok bol true.

Príklad použitia :

#!/bin/bash
x=5
y=10
if [ "$x" -eq 5 ] && [ "$y" -eq 10 ]; then
  echo "Obe podmienky sú splnené"
else
  echo "Nie sú splnené obe podmienky"
fi

Podobné použitie má i logický súčet. Nasledujúci príklad to ilustruje:

#!/bin/bash
x=3
y=2
if [ "$x" -eq 5 ] || [ "$y" -eq 2 ]; then
  echo "Aspon jedna podmienka je splnená"
else
  echo "Nie je splnená žiadna podmienka"
fi

Ďalšie využitie konštrukcie AND a OR je v tkzv. zoznamoch. Konštrukcia zoznamu AND umožňuje prevádzať sadu príkazov tým spôsobom, že ďalší príkaz je prevedený len v prípade úspešného prevedenia všetkých predchádzajúcich príkazov. Má následujúcu syntaxu:

príkaz1 && príkaz2 && príkaz3 && ...

Začne sa zľava, je prevedený prvý príkaz a pokiaľ vráti hodnotu true, prevedie sa ďalší príkaz vpravo od nej. Tak to pokračuje, kým niektorý z príkazov nevráti hodnotu false a tým prevádzanie zoznamu skončí. Konštrukcia && testuje hodnotu predchádzajúceho príkazu.

Každý príkaz je prevádzaný nezávisle, takže v jednom zozname môžeme zmiešať mnoho rôznych príkazov, ako plynie z nižšie uvedeného scriptu. Zoznam AND vráti hodnotu true, keď sú všetky príkazy úspešne prevedené, v opačnom prípade vráti hodnotu false.

V nasledujúcom scripte prevedieme príkaz touch file_1 (čím kontrolujeme existenciu súboru file_1 a pokiaľ neexistuje, tak ho vytvoríme) a potom odstránime súbor file_2. Potom pomocou zoznamu AND otestujeme existenciu každého zo súborov a vypíšeme nejaký text.

#!/bin/bash
touch file_1
rm -f file_2
if [ -f file_1 ] && echo "hello" && [ -f file_2 ] && echo "there"
then
  echo -e "in if"
else
  echo -e "in else"
fi
exit 0

Výstup programu bude nasledujúci :

socket@blackbox:~$ ./script_touch.sh
hello
in else

funkcia scriptu :

Príkazy touch a rm zaistia požadovaný stav súborov v aktuálnom adresári. Zoznam && potom prevedie príkaz [ -f file_1 ], ktorý bude úspešný, prevedie sa príkaz echo. Ten bude taktiež úspešný (príkaz echo vždy vracia hodnotu true). Potom je prevedený tretí test, [ -f file_2 ], ktorý vráti false, pretože tento súbor neexistuje. Pokiaľ bol posledný príkaz neúspešný, neprevedie sa posledný príkaz zoznamu echo. Výsledok zoznamu && je false, pretože jeden z príkazov zoznamu zlyhal, tým pádom sa prevedie vetva else príkazu if.

Konštrukcia zoznamu OR umožňuje prevádzať skupinu príkazov, dovtedy, kým jeden nevráti hodnotu true, potom skončí. Syntax je následujúca:

príkaz1 || príkaz2 || príkaz3 || ...

Príkazy sú prevádzané zľava, jeden po druhom. Tak to pokračuje, kým niektorý z príkazov nevráti hodnotu true a tým prevádzanie zoznamu skončí.

Zoznam || je podobný zoznamu && s tým rozdielom, že tu musí predchádzajúci príkaz vrátiť false.

Nasledujúci príklad je modifikácia minulého príkladu, líšia sa jedine v použití zoznamu OR namiesto zoznamu AND a taktiež nevytvorí súbor file1. Priebeh však bude vďaka tejto konštrukcii iný.

#!/bin/bash
rm -f file_1
if [ -f file_1 ] || echo "hello" || echo "there"
then
  echo -e "in if"
else
  echo -e "in else"
fi
exit 0

Výstup programu bude :

socket@blackbox:~$ ./script.sh
hello
in if

funckia scriptu:

Prvé dva riadky len nastavujú súbory pre zbytok scriptu. Prví príkaz [ -f file_1 ], zlyhá, pretože daný súbor neexistuje. Potom je prevedený príkaz echo. Ten vráti hodnotu true a potom, ked nie sú žiadne dalšie príkazy zoznamu || prevedené. Príkaz if bude úspešný, pretože jeden z príkazov zoznamu || (echo) vrátil hodnotu true.

Výsledok oboch týchto konštrukcií je výsledkom posledného prevedeného príkazu.

Zoznam je vyhodnocovaný podobným spôsobom, akým je v jazyku C vyhodnocovaných viac podmienok. K určeniu výsledku je prevedený len minimálny počet príkazov. Príkazy, ktoré výsledok nemôžu zmeniť, sa neprevedú. Tomu hovoríme tkzv. skrátené vyhodnocovanie.

Skombinovaním týchto dvoch konštrukcií dostávame "raj logikov". Vyskúšajte:

[ -f file_1 ] && príkaz pre true || príkaz pre false

Pokiaľ bude test úspešný, prevedie sa prvý príkaz, v opačnom prípade druhý. S takýmito menej obvyklými zoznamami je vždy lepšie trošku experimentovať.

Pokiaľ chcete použiť viac príkazov na mieste, kde je povolený príkaz jeden, napríklad v zozname AND alebo OR, môžete si pomocou zložených zátvoriek vytvoriť blok príkazov.
príklad :

get_confirm && {
  grep -v "^${cdcatnum}," $tracks_file > temp_file
  mv $temp_file $tracks_file
  echo
  add_record_tracks
}

----------------------------------------------------------------------------------------------
Tak to by myslím na dnes stačilo. Dúfam že sa vám dnešná časť seriálu páčila a že aspoň niekomu padne na úžitok.

    • Re: Coding in BASH #5 08.01.2008 | 00:52
      Avatar blackhole_tommyhot   Používateľ

      Nice, akurat by som tento kod riesil trochu inak:

      #!/bin/bash
      echo -n "Zadaj svoj nick: "
      read meno
      if [ -z "$meno" ]; then
        echo "Ty si mi nepovedal svoj nick!"
        exit
      fi
      echo "Zdravím ta $meno!"

      Urobil by som to radsej takto:

      #!/bin/bash
      echo -n "Zadaj svoj nick: "
      read meno
      until [ "$meno" = "" ]; then
        echo "Ty si mi nepovedal svoj nick!"
        echo -n "Zadaj svoj nick: "
      fi
      echo "Zdravím ta $meno!"

      Pri kratuckom scripte ta tvoja moznost nevadi, ale pri dlhsom scripte, kde musi user zadat viac vstupov urcite nasere ak zada blbost a program sa exitne a musi ist zadavat vstupy od znova..

      Inak prebehni si este tie kody, v niektorych mas drobne syntakticke chyby (uvodzovky) :)

      Btw dik, o tom bloku prikazov {} som nevedel, mam taky pocit.. uz som dlho nic neklepal v bashi.

      ----------
      tommyhot@hackingmachine:~$ microsoft &> /dev/null

      • Re: Coding in BASH #5 08.01.2008 | 14:25
        Avatar blackhole_socket   Používateľ

        uvodzovka doplnená :)) ... inak ten tvoj script je tiež ok ale na ifku môžeš priviesť na vystup štruktury reply daného vstupu (funkcie ) [prakticky to iste ako until"" ], takže ten exit tam je iba preto že to je mini script ;)
        _______________________________________________________
        Gentoo READY ! ...

      • Re: Coding in BASH #5 09.01.2008 | 10:43
        Avatar blackhole_matej   Používateľ

        Tvoj skript fungovať nebude, pretože:

        • until ... do ... done (nie then-fi)

        • v cykle nemáš read
        • podmienku za until máš opačnú, ako by mala byť

        A navyše until sucks, používajú ho iba spaskalisti... while je čitateľnejšia konštrukcia, netreba si v hlave robiť stále negácie.

        • Re: Coding in BASH #5 09.01.2008 | 11:13
          Avatar blackhole_tommyhot   Používateľ

          Aha mas pravdu, nejako som to prehliadol :(
          ----------
          tommyhot@hackingmachine:~$ microsoft &> /dev/null

    • Re: Coding in BASH #5 08.01.2008 | 16:18
      Dare_Devil   Návštevník

      Smiem laiksku otazku? Aky je rozdiel medzi && a AND / || a OR ? Je mozne vyberat si medzi zapisom v kazdom progr. jazyku alebo je v niektorych presne urcene ze pracuju len s urcitym zapisom? Co je univerzalnejsie? Mam pocit ze vplyv na chod podmienky to nemoze mat.
      ------------
      Iba dve veci su vecne: vesmir a ludska hlupost

      • Re: Coding in BASH #5 08.01.2008 | 18:00
        Avatar blackhole_matej   Používateľ

        Rozdiel je taký, že AND/OR je slovné pomenovanie - také príkazy v bashi neexistujú, použiť môžeš &&/|| (číta sa logický AND, OR).

        rm -rf / && echo "I feel so free!" || (echo "Error"; exit 1)

        • Re: Coding in BASH #5 08.01.2008 | 19:30
          Dare_Devil   Návštevník

          Dakujem

    • Re: Coding in BASH #5 09.01.2008 | 10:17
      Avatar blackhole_ventYl   Používateľ

      Kurva... 4 sekundy pozeram na text a uz vidim hrubku. Sa naucte pravopis dementi.

      ---
      Cuchat s nadchou, to je ako sniffovat bez promiscu.

      --- Cuchat s nadchou, to je ako sniffovat bez promiscu.
      • Re: Coding in BASH #5 29.06.2009 | 18:01
        W1cK3d   Návštevník

        ale clanok bol dobry pan redaktor
        _________________________________________________________________________________
        kristusky a stare tricko...ITckar

        • Re: Coding in BASH #5 29.06.2009 | 18:43
          Avatar Maff   Používateľ

          To ze komentujes rok a pol mrtvy clanok ti nevadi vsak? :)

          • Re: Coding in BASH #5 30.06.2009 | 20:09
            W1cK3d   Návštevník

            nevsimol som.. :(( len som zhanal nieco o BASHi a na Bhole daco bolo..
            _________________________________________________________________________________
            kristusky a stare tricko...ITckar