Skriptovanie v shelli: Špeciálne premenné

Ďalšie špeciálne premenné

Parametre príkazového riadka

Minule sa spomínalo, že parametre príkazového riadka sú k dispozícii v premenných 19. Čo ak chcete iterovať cez všetky parametre a s každým z nich niečo spraviť? Tie sú dostupné v premennej @.

Hlúpy príklad:

#!/bin/sh
for WORD in "$@"
do
        echo $WORD
done

Pamätáme si na for? Iteruje cez zoznam slov oddelených medzerou. Premenná $@ v úvodzovkách (opakujem, v úvodzovkách) zoberie parametre z príkazového riadka, rozseká ich na jednotlivé slová a každé z nich navyše expanduje.

(Bokom: cyklus for iteruje v skutočnosti cez slová oddelené prvým znakom premennej IFS, ale to teraz nemusíme rozoberať.)

Spusťme cez

./iterate.sh on the fourth day of christmas

Vypíše

on
the 
fourth 
day 
of 
christmas

Ale! Pozor na úvodzovkovanie! V tomto prípade (v súlade so shellovskou tradíciou) je on the fourth day považovaný za jedno slovo. Toto:

./iterate.sh "on the fourth day" of "christmas"

Vypíše:

on the fourth day
of
christmas

Mimochodom, vo for cykle môžeme vynechať klauzulu in.... Oba zápisy sú ekvivalentné:

for WORD in "$@"

a

for WORD

Ak teda in ... vynecháme, for bude prechádzať cez parametre z príkazového riadka.

Pozor na úvodzovky alebo $@ vs "$@"

Dajte si veľký pozor na úvodzovky! Ak ich vynecháte, premenná sa expanduje na slová, kde sa úvodzovky budú ignorovať:

for WORD in $@

pre vstup:

./iterate.sh "on the fourth day" of "christmas"

Vypíše:

on
the
fourth
day
of
christmas

Premenná $*

V krátkosti: smrteľníci ju môžu ignorovať. Vystačíte si s $@.

Premenná $* je druhá, mätúca, premenná s parametrami príkazového riadka. Ak ju použijete v úvodzovkách, expanduje na jedno shellovské slovo, kde budú parametre oddelené prvým znakom z premennej IFS — obvykle medzerou. Cyklus for potom následne nebude iterovať cez jednotlivé parametre oddelené medzerou, pretože dostane na vstup len jedno shellovské slovo, ktoré vypíše

#!/bin/sh
for WORD in "$*"
do
        echo $WORD
done

Spusťme

./iterate.sh "on the fourth day" of christmas

Výsledok:

on the fourth day of christmas

Ak ju použijete bez úvodzoviek, správa sa presne tak ako $@ bez úvodzoviek, čo bolo spomenuté vyššie: zoberie parametre, pričom vôbec nebude brať ohľad na úvodzovky: "on the fourth day" bude považovať za štyri slová.

Tieto dve premenné sa často pletú, ale ako bolo napísané vyššie: pre typické situácie si úplne vystačíte s $@. V úvodzovkách, samozrejme.

Parametre príkazového riadka (iný príklad)

Urobme si jednoduchý skript, ktorý dostane parametre na vstup a každý z nich prehodí na proper case, teda prvé písmená každého slova budú veľké:

./propercase.sh driving home for christmas

S výsledkom:

Driving Home For Christmas

Idea bude nasledovná: jednotlivé slová budú parametre príkazového riadka. Z každého slova vezmeme prvé písmeno, to prevedieme na VEĽKÉ, následne zoberieme zvyšok slova, ktorý prevedieme na malé písmená a celé to zlepíme.

Získanie prvého písmena dosiahneme cez head:

echo traky | head -c1

vráti:

t

Odsekávanie prvého písmena (teda získanie zvyšku slova) získame cez expanziu

WORD=traky
echo ${WORD#?}

vráti:

raky

Modifikátor expanzie # totiž odsekáva prefix a otáznik je zástupný symbol pre „ľubovoľný znak” (analógia bodky v regulárnych výrazoch).

Preklad veľkých písmen na malé a naopak získame cez tr.

#!/bin/sh
for WORD
do
        INITIAL=$(echo "$WORD" | head -c1 | tr [:lower:] [:upper:])
        REST=$(echo ${WORD#?} | tr [:upper:] [:lower:])
        printf "%s " $INITIAL$REST
done
echo

Finta s printf slúži na to, aby sa slová vypísali vedľa seba (echo by ich totiž nasypalo pod seba). Posledné echo je estetické: zapíše nový riadok za poslednou položkou.

Zisťovanie návratovej hodnoty: $?

Tradícia UNIXovských programov hovorí, že program môže po dobehnutí vrátiť operačnému systému číselnú návratovú hodnotu, na základe ktorej sa dá následne rozhodnúť, či beh skončil v poriadku, alebo či nastala nejaká chyba. (Je to akýsi praotec výnimiek z objektového programovania.) Nula tradične znamená „dobehol som v poriadku” a akákoľvek iná hodnota indikuje chybu.

Vezmime si taký grep. Ak spustíte hľadanie a reťazec sa nájde, vráti sa exit code rovný nule. Ak sa reťazec nenájde, exit code bude rovný jednej.

V shelli sa to dá otestovať špeciálnou premennou ?. Hľa, ukážka:

grep NEEXISTUJUCI_POUZIVATEL /etc/passwd 

A následne

echo $?

čo dá výsledok

1

Inak, tento exit code je presne tá hodnota, ktorá sa vráti z funkcie main() v céčkovských programoch.

Príklad (slovník)

Založme si súbor words.txt, ktorý bude predstavovať prekladový slovník. Po riadkoch budú dvojice oddelené dvojbodkami:

pes:dog
macka:cat
slon:elephant
vlk:wolf
liska:fox

Skript bude vyzerať nasledovne:

#!/bin/sh
DICTIONARY=words.txt

for WORD
do
        RESULT=$(grep "$WORD" "$DICTIONARY")
        if [ "$?" == 1 ]
        then
                echo "Word not found: $WORD"
        else
                echo ${RESULT##*:}
        fi
done

Iterujeme cez parametre príkazového riadka (premenná WORD) a skúsime grepnúť súbor so slovníkom. Ak sa slovo nenájde, grep vráti jednotku a vypíše hlášku, že slovo sa nenašlo. V opačnom prípade odsekneme z riadka s dvojicou slov všetky znaky po prvú dvojbodku, čím získame preklad.

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *