Programargumentumok, shell változók
Az előbbiek folyamán már futólag találkoztunk a shell változóival (shell variables, parameters), például ilyen volt az átdefiniálható prompt, vagy az állományok keresését biztosító PATH változó. A shell-változók két fajtáját különböztetjük meg, egyik a hagyományos programozási nyelvekben megszokotthoz hasonló változó, a másik az úgynevezett pozicionális paraméter.
A közönséges shell-változónak akár parancsszinten, akár egy programban értéket lehet adni, azt le lehet kérdezni, illetve módosítani. A pozicionális paraméterek azok az argumentumok, amelyeket végrehajtáskor átad a shell a meghívott shellscriptnek (például a myprog 23 /tmp parancsban két pozicionális paraméter, a 23 és a /tmp adódik át myprog-nak). Ellentétben a közönséges shell-változókkal, a pozicionális paraméterek értékét a felhasználó soha nem változtathatja meg, azokat csak lekérdezni tudja. A pozicionális paraméterekről a shell programozás kapcsán még lesz szó, egyelőre a közönséges shell-változókkal foglalkozzunk.
Egy shell-változónak igen egyszerűen adhatunk értéket, a neve után egy egyenlőségjelet gépelünk, s utána a változó (új) értékét. Az egyenlőségjel körül nem lehetnek szóközök, s maga a shell-változó értéke is csak egy szó lehet, így ha szóközt vagy tabulátort is tartalmaz, akkor valamelyik idézőjelpárral kell körülvenni. Az alábbi példa az elsődleges promptot definiálja át, melynek változója PS1:
$ PS1='Yes, dear? '
Yes, dear? pwd
/users/demo
Yes, dear? PS1='$ '
$
A shell-változók értékét a set paranccsal lehet lekérdezni (a set maga számtalan, igen eltérő funkcióval rendelkező parancs, a shell-programozásról szóló fejezetben több alkalmazási lehetőségére visszatérünk még).
$ set
EDITOR=vi
HOME=/users/demo
IFS=
LOGNAME=demo
MAIL=/usr/mail/demo
MAILCHECK=600
MANPATH=/usr/man:/usr/contrib/man:/usr/local/man
PAGER=pg
PATH=/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin:usr/openmail/bin:.
PS1=$
PS2=>
SHELL=/bin/sh
TERM=sun-cmd
TZ=MET-1METDST
$
A fenti példában látható változók rendszerváltozók, amelyeket bejelentkezésünkkor már beállított a shell. Ha saját magunk definiálunk változókat, azok is láthatóak a listán. A foglalt nevek nagybetűsek, míg az általános konvenció szerint a felhasználó által definiált shell-változók rendszerint kisbetűsek.
Hogy a shell-programozásban hogyan és mire használjuk a shell-változókat, arra a 10. fejezetben részletesen visszatérünk. Itt és most csak olyan kérdésekkel foglalkozunk, amelyek az interaktív shell használat során előkerülhetnek.
Nézzünk néhány példát, hogy mire is használhatunk egy shell-változót. Ha például van egy gyakran "látogatott" katalógusunk, akkor annak nevét egy shell-változóban elmenthetjük, s a továbbiakban nem kell annak teljes nevét begépelnünk, elég, ha a shell-változó nevét adjuk meg a cd parancs paramétereként:
$ dir=/usr/catman/u_man/man1
$ echo $dir
/usr/catman/u_man/man1
$ cd $dir
$ pwd
/usr/catman/u_man/man1
$
A fenti példából látható, hogy a var shell-változó értékére a $var módon hivatkozunk.
A rendszer által állított fontosabb shell-változók
Az alábbi táblázatban a rendszer által állított legfontosabb shell-változókat tekintjük át.
HOME
A cd parancs default értéke, a felhasználó saját (bejelentkezési) katalógusára állítja be a rendszer.PATH
A parancsok keresési útvonalát állítja be, azaz hogy a shell hol keresse a végrehajtandó fájlokat. Az egyes elemeket kettőspont (:) választja el egymástól.CDPATH
A cd parancs számára beállítható keresési útvonal, szintén kettősponttal szeparálva. Ha e változó be van állítva, relatív elérési útvonalak megadásakor a shell a CDPATH-ban felsorolt összes elérési útvonalhoz megpróbálja illeszteni az általunk begépelt relatív nevet, és ha talált ilyet, oda vált. Például ha CDPATH=/abc, akkor ha kiadunk egy cd bin parancsot, a shell megnézi, hogy létezik-e /abc/bin katalógus, s ha igen, oda vált.MAILCHECK
Megadja (másodpercekben), hogy milyen gyakran ellenőrizze és írja ki a shell az új posta érkezését. Alapértelmezése 600. Ha értéke 0, minden parancs kiadása után, a prompt kiírása előtt ellenőriz.PS1,PS2
Az elsődleges és másodlagos prompt. A default értékek a "$", illetve ">".TERM
A felhasználó által használt terminál típusa.USER
LOGNAME
A felhasználó neve (bejelentkezési azonosítója).IFS
Belső mezőhatárolók: azon karakterek, amelyek a shell szavait elválasztják (default megadása a szóköz, a tabulátor és az újsor karakterek).TERMINFO
A curses és terminfo terminálfüggetlen képernyőkezelő rutinok számára definiál külön katalóguselérési útvonalat.TZ
A helyi időzóna.Nagyon gyakran van szükségünk arra, akár interaktív módban, akár script-ekben, hogy a saját kiindulási katalógusunkra hivatkozzunk; rendszerint azért, mert onnan kiinduló katalógus- vagy fájlneveket szeretnénk megadni. Ilyenkor igen hasznos (és gyakran kevesebb gépelést is eredményez) a HOME változó használata. A legfontosabb érv azonban az, hogy ha bármilyen oknál fogva megváltozik környezetünk, vagy egy általunk írt shellscript-et más gépre szeretnénk átvinni, a HOME változó használata biztosítja a rendszerfüggetlenséget - akárhol, akármilyen UNIX-os gépen is dolgozunk, a HOME változó értéke be lesz állítva, s nyugodtan felhasználhatjuk.
A PATH változó a végrehajtandó programok keresési útvonalát adja meg. A shell mindig balról jobbra értékeli ki, tehát az elsőnek megadott katalógus-
névben keres először, aztán jön a következő és így tovább. Ellentétben a DOS-sal, itt a kurrens katalógusnév nem értetődik bele a keresési útvonalba! Ezért, ha a PATH változónkban nem szerepel, ne lepődjünk meg, hogyha a shell nem látja meg az "orra előtt lévő" végrehajtandó fájlt a kurrens katalógusban, s "Command not found" vagy hasonló hibaüzenetet ad. A kurrens katalógust vagy a '.' karakterrel, vagy egy üres mezővel adhatjuk meg. (Meg kell jegyeznünk, hogy biztonsági megfontolásokból nem célszerű a kurrens katalógust megadni a keresési útvonalban, de ha mégis rászánjuk magunkat, mindenképpen a legvégére tegyük, valahogy így:
PATH=/bin:/usr/bin:/usr/local/bin:$HOME/bin:.
A TERM változónak fontos szerep jut mindannyiszor amikor valamilyen editort futtatunk, képernyőn listázunk, vagy távoli gépekre jelentkezünk be. Ezekben az esetekben ugyanis mindig arra van szükség, hogy valamilyen terminálfüggő megjelenítést hajtsunk végre, márpedig számtalan fajta terminál létezik, a legbutább teletype jellegűektől elkezdve a nagyfelbontású grafikus képernyőkig. Hogy a terminálfüggetlen működést meg lehessen oldani, a UNIX egy terminál (és nyomtató) adatbázist is tartalmaz. BSD UNIX rendszerekben ez egyetlen hatalmas fájl, a /etc/termcap, System V alapú rendszerekben egy külön katalógusfa, rendszerint a /usr/lib/terminfo katalógus alatt, ahol minden gyakoribb termináltípus jellemzői szabványos módon fel vannak sorolva. Ha egy programban ezek után kiadjuk például a "menj a képernyő HOME (bal felső) pozíciójába" parancsot, a program a TERM shell-változó alapján meghatározza terminálunk típusát, a terminfo vagy termcap adatbázisban megnézi, hogy az adott terminálnál milyen karakterszekvencia felel meg a kívánt műveletnek, majd végrehajtja azt.
Egy létrehozott shell-változó mindig ahhoz a shell-hez tartozik, amely létrehozta, és a shell gyermekeinek, tehát a shell által indított programoknak nem adódik át automatikusan, mint ezt az alábbi példa is mutatja:
$ x=Hello
$ echo $x
Hello
$ sh # uj shell-t inditunk
$ echo $x
$ exit # most vissza az elozo shell-be
$ echo $x
Hello
$
Az előbbiek miatt, ha azt akarjuk, hogy egy változót a leszármazott processzek is megkapjanak, azt exportálni kell, ami az export var parancs kiadásával történik:
$ x=Hello; export x
$ sh
$ echo $x
Hello
$
A pozicionális paramétereket, pontosabban azok értékét a $n megadással jelöljük, ahol n egész szám kell hogy legyen (régebbi shell implementációk csak 9 pozicionális paramétert engedélyeztek, $1-től $9-ig). $1 a shellscriptnek átadott első paraméter, $2 a második, stb. $0 hagyományosan a shellfile nevét tartalmazza. Az előzőekben szerepelt példát véve, ha a
myprog 23 /tmp
parancsot adjuk ki, akkor a myprog shellscript a következő pozicionális paramétereket kapja: $0=myprog, $1=23, $2=/tmp. Ennek ismeretében most az nf program példájára hozzuk létre az nf1 programot, amelyik nem a kurrens, hanem tetszőleges katalógusban található fájlok számát írja ki. E shellscriptnek egy paramétere lesz, mégpedig a listázandó katalógus neve - a megfelelő helyen (tehát az ls parancs paraméterezésénél) - a $1 jelöléssel hivatkozunk rá:
$ echo 'ls $1 | wc -w' >nf1; chmod +x nf1
$ ls; nf1
FULL-INDEX file1 newfilee2 ravasz temp
akarmi newdir nf semmi text
file newfile nf1 sendmail.cf
14
$
$ ls /usr; nf1 /usr
adm diag local nettest pub tsm
archive doc lost+found news sam users
backup etc mail old softbench
bin include man openmail spool
boot keysh netdemo pc-dos sysver
contrib lib netls preserve tmp
32
$
Az eddig tárgyaltakon kívül a Bourne shell még az alábbi shell változók értékét is állítja:
# A meghívott (futó) program pozicionális paramétereinek száma. Programciklusokban használható jól, például a script hívási paramétereinek (argumentumlistájának) feldolgozásakor.
? A legutolsónak végrehajtott parancs visszatérési értéke.
$ A futó shell folyamatazonosítója. Shellprogramokban ideiglenes fájlnevek képzésére használható, miután egy program folyamatazonosítója egyedi érték. Ha tehát shell scriptünkben egy ideiglenes fájlnak mondjuk a /tmp/myscript.$$ nevet adjuk, akkor garantált, hogy akárhány felhasználó is futtatja egyidőben ezt a scriptet, mindegyik script más-más néven hozza létre az ideiglenes állományait.
! A legutolsónak indított, háttérben futtatott processz folyamatazonosítója.
Arról már volt szó, hogy egy var shellváltozóra (paraméterre) a $var vagy ${var} megadással hivatkozhatunk; a shell ilyenkor megpróbálja behelyettesíteni a változó értékét. Az alábbiakban a behelyettesítések néhány speciális esetét nézzük meg.
${
var:-value} Ha a var változó be van állítva, s értéke nem nulla, behelyettesítéskor a shell ezzel az értékkel dolgozik; ellenkező esetben value-t adja vissza. Így lehet default paramétereket beállítani shell scriptekben, ha argumentum nélkül hívták meg őket. Például ha a ${1-/tmp} hivatkozást használjuk, ha scriptünket paraméter nélkül hívják meg, $1 helyett a /tmp értéket adja vissza.${
var:=value} Ha a var változó nincs beállítva, vagy nullváltozó, var-t value-ra állítja, s ezután helyettesíti be var értékét. Például ${name:=first_name} esetén, ha a name változó nincs beállítva, first_name változóértékét fogja behelyettesíteni.${
var:?value} Ha var be van állítva és nem nullváltozó, behelyettesíti értékét, egyébként kiírja a value stringet és kilép a shellből. (Ha value nem lett beállítva, a "parameter null or not set" üzenetet kapjuk.${
var:+value} Ha var be van állítva és nem nullváltozó, value-t adja vissza, egyébként nem helyettesít be semmit.A fenti változóhivatkozások megadhatóak a kettőspont nélkül is, ebben az esetben a shell csak azt vizsgálja, hogy a változók be vannak-e állítva, az értéküket nem ellenőrzi.