En la antaŭa ĉapitro ni vidis, ke komandoj donitaj al ŝelo povas esti storataj en "skriptoj". La komanda lingvo de ŝelo estas speco de programad-lingvo, kaj oni povas verki verajn programojn en ĝi.
Kutime la elementoj de tiaj ŝel-programoj ne estas elementaj operacioj, kiel en "vera" programad-lingvo, ekzemple aritmetikaj aŭ logikaj operacioj. Ŝela operacioj ofte estas mem potencaj komandoj, kiuj prilaboras dosierojn kaj povas konsumi multe da tempo. Tamen ankaŭ elementaj operacioj estas eblaj.
Ni koncentriĝas tie ĉi al la programado per la borna ŝelo, pro du kialoj:
Rimarkigo: Kutime ŝelaj skriptoj komencas per la teksto "#!/bin/sh"; tio indikas, ke ili estas por la borna ŝelo, kies dosiera nomo estas /bin/sh. Tiun ĉi linion ni ne metas en la ĉi-subaj ekzemploj.
Ankaŭ kiam oni ne uzas skriptojn, sed simple tajpas al la komanda linio, oni ofte devas doni al komando parametrojn. Parametro povas ekzemple esti la nomo de iu dosiero, kiun la komando prilaboru. Jen ekzemploj pri la komando wc, kiu nombras la signojn, vortojn kaj liniojn en dosiero:
$ wc unuateksto.txt 249 1105 8319 unuateksto.txt $ wc unuateksto.txt duateksto.txt 249 1105 8319 unuateksto.txt 237 991 7749 duateksto.txt 486 2096 16068 totalo $ wc "nomo kun spacoj.txt" 220 1003 9488 nomo kun spacoj.txt |
La lasta ekzemplo montras specialan kazon: La dosiera nomo enhavas spacetojn, kaj la spaceto estas uzata de la ŝelo por disigi parametrojn. Do necesas iel kunigi la partojn de la nomo, kaj tio okazas per citiloj ("").
Longajn listojn de dosieraj nomoj ne ĉiam necesas tajpi: La ŝelo mem povas konstrui ilin, se la dosieroj jam ekzistas. Por tio utilas la stelo (*), kiu povas anstataŭi ajnan vicon de signoj. Se nia dosierujo enhavas la tri teksto-dosierojn el la lasta ekzemplo kaj ni volas nombri iliajn signojn, sufiĉas jena komando:
$ wc *.txt
237 991 7749 duateksto.txt
220 1003 9488 nomo kun spacoj.txt
249 1105 8319 unuateksto.txt
706 3099 25556 totalo
|
La plej simpla speco de ŝela programado estas la vicigo (ĉenigo) de pluraj komandoj, tiel ke ili estas rulataj unu post la alia. Por tio necesas dividi la komandoj, tiel ke la ŝelo sciu, kie komenciĝas nova komando. Por tio estas du ebloj: nova linio aŭ punktokomo (;).
Ni konsideru etan skripton, kiu salutas la uzulon kaj informas lin pri la dato kaj la tempo. Tiu skripto nomiĝu saluto1. Unue ni eligas informon pri la skripto (per la komando ls -l), poste ni eligas ĝian enhavon (per la komando cat), fine ni rulas la skripton:
$ ls -l saluto1 -rwxr-xr-x 1 u1 kurso 73 2008-08-10 13:58 saluto1 $ cat saluto1 echo "Saluton! Dato kaj tempo estas:" date echo "Havu plezuran laboron!" $ ./saluto1 Saluton! Dato kaj tempo estas: dim Aŭg 10 13:59:26 CEST 2008 Havu plezuran laboron! $ |
Egale bone ni povas uzi punktokomojn:
$ cat saluto2 echo "Saluton! Dato kaj tempo estas:"; date; echo "Havu plezuran laboron!" $ ./saluto2 Saluton! Dato kaj tempo estas: dim Aŭg 10 13:59:48 CEST 2008 Havu plezuran laboron! $ |
Ni vidis, ke komandoj ofte havas parametrojn, kaj ke la parametrojn oni disigas per spacetoj. Foje oni deziras doni al skripto parametrojn kaj uzi ilin interne de la skripto. Por tio servas la dolara signo ($; pretere, ĝi havas multajn funkciojn en ŝela programado). Ekzemple, se iu volas havi la mallongan komandon "l" anstataŭ "ls -l", li povas uzi skripton nomatan "l":
$ cat l ls -l $1 $ l unuateksto.txt 249 1105 8319 unuateksto.txt |
En tiu formo la komando uzas nur unu parametron; oni povas doni pli, sed ili ne estos uzataj. Por povi uzi pli da parametroj eblas ekzemple aldoni " $2 $3 $4 $5", sed tiam la limo estus ĉe 5 parametroj. Por havi ajnan nombron da parametroj oni uzas "$*":
$ cat l ls -l $* $ l unuateksto.txt duateksto.txt 249 1105 8319 unuateksto.txt 237 991 7749 duateksto.txt 486 2096 16068 totalo |
Multaj uniksaj komandoj laboras pri dosieroj; ekzemple la komando wc nombras liniojn en dosieroj. Ĝenerale tiaj komando povas labori ankaŭ pri teksto, kiun tajpas uzanto. Por tio oni vokas la komandon sen doni nomo(j)n de dosiero(j). Ekzemple:
$ wc Jen iom da teksto, kiun tajpas la uzulo. ^D 2 8 41 |
Oni diras, ke la uzulo tajpis tekston al la "norma eniro" de la komando. Jen kelkaj rimarkindaj aferoj pri la ekzemplo:
Pretere, la vojo, al kiu la komando skribas sian rezulton, estas nomata la "norma eliro". Normale tiu norma eliro estas ligita al la terminalo, kie la uzulo povas legi ĝin.
La ŝelo ofertas simplan vojon por rekonekti la normajn eniron kaj eliron al dosieroj. Por tio servas la signoj "<" kaj ">", metataj antaŭ la nomon de dosiero. Vokate tiel, komando legas de iu dosiero kaj skribas al iu dosiero, sed kredas legi de la norma eniro kaj skribi al la norma eliro. Tial ekzemple la komando "wc" tiam ne indikas dosieran nomon, kvankam ĝ fakte legas de dosiero:
$ ls -l -rw-r--r-- 1 u1 kurso 8319 2008-08-10 14:48 unuateksto.txt $ wc |
Oni nomas tiun teknikon "transdirektado" aŭ "redirektado" de la eniro/eliro. La redirekta komando do aŭtomata kreis la dosieron rezulto.txt kaj skribis en ĝin la rezulton de la komando wc.
Plia speco de redirektado estas la uzo de "tuboj". Per tubo oni povas ligi la eliron de unu komando al la eniro de alia komando, sen uzi dosieron. Tubon en ŝela skripro oni konstruas per la signo "|":
$ ls rezulto.txt unuateksto.txt $ ls | wc 2 2 27 $ ls | wc -l 2 |
La komandoj "wc" do nombris la liniojn, vortojn kaj signojn en la rezulto de la komando "ls"; kun la opcio "-l" ĝi nombris nur la liniojn. Tiel oni povas nombri la dosierojn en dosierujo.
La ŝelo povas ankaŭ difini variablojn por memori valorojn. Por tio oni simple uzas la nomon de la variablo, egaleco-signon (=) kaj la valoron. Kutime oni uzas majusklojn por la nomo, sed tio ne estas strikta regulo.
Per la dolara signo kaj kunigaj krampoj ("${…}") oni retrovas la valoron de variablo:
$ VARIABLO1="Iom da teksto" $ echo ${VARIABLO1} Iom da teksto |
Tre utila afero estas, ke eblas memori en variablo la rezulton de iu komando. Por tio oni uzas la "dekstran kornon" (`). Ni demonstras tion per la supre uzita komando ls | wc -l, kiu nombras la dosierojn en dosierujo:
$ ls rezulto.txt unuateksto.txt $ ls | wc -l 2 $ DOSIEROJ=`ls | wc -l` $ echo "En la dosierujo estas ${DOSIEROJ} dosieroj." En la dosierujo estas 2 dosieroj. |