Yksinkertaisia muuttujia luodaan ja niille asetetaan arvo tyyliin
varname=value
Huom. yhtäsuuruusmerkin ympärillä ei saa olla välilyöntejä.
Muuttujanimessä sallittuja merkkejä ovat kirjaimet, numerot ja alaviiva; ensimmäisen on oltava kirjain.
Muuttujan arvoon viitataan syntaksilla $varname tai ${varname}; ts. jos komentorivillä esiintyy $varname, se korvataan muuttujan varname arvolla.
Muuttujanimi on suljettava aaltosulkuihin silloin, kun seuraavakin merkki voisi olla osa muuttujanimeä (se on kirjain, numero tai alaviiva). Vertaa:
K=a Kalle=n echo $Kalle echo ${K}alle
Muuttujan voi hävittää komennolla unset varname (yksitellen - POSIXin unset ei ymmärrä mitään jokerimerkkejä).
Muuttujasta voi tehdä vakion komennolla readonly varname[=value]. Kaikki vakiot voi listata komennolla readonly -p. Vakion arvoa ei voi muuttaa eikä sitä voi hävittää unsetilla.
Ympäristömuuttujat eroavat sisäisistä siinä, että ne periytyvät aliprosesseille. Muuttujan voi määritellä ympäristömuuttujaksi komennolla export. Käänteistä toimintoa ei ole mutta ympäristömuuttujankin voi hävittää unsetilla.
export varname...
Lisäksi jos optio -a on voimassa, kaikista luotavista muuttujista tulee automaattisesti ympäristömuuttujia. Ympäristömuuttuja voi olla vakio (readonly), mutta readonly-attribuutti ei välttämättä periydy (riippuu shellistä).
Edellisten lisäksi shell käyttää joukkoa erikoismuuttujia, jotka tunnistaa siitä, että ne eivät ala kirjaimella. Niitä ei voi exportata ja ne käyttäytyvät joissakin tilanteissa muutenkin eri tavoin kuin normaalit muuttujat.
Jos sh-skriptille annetaan argumentteja (optioiden lisäksi), ne talletetaan ns. positioparametreihin (positional parameters) $1, $2,... (Funktion sisällä positioparametrit viittaavat funktion kutsussa annettuihin argumentteihin, kuten edellä on todettu.)
Sen lisäksi sh määrittelee automaattisesti seuraavat parametrit:
Kaksi ensimmäistä tarvitsevat lisäselitystä.
Ne eroavat toisistaan
ainoastaan siinä, miten ne käyttäytyvät tuplalainausmerkeissä ":
"$*" on yksi merkkijono joka sisältää kaikki parametrit
välilyönnillä eroteltuina (tai oikeammin $IFS:n ensimmäisellä
merkillä - enemmän siitä myöhemmin). Ts.
echo "$*" käyttäytyy kuin
echo "$1 $2 $3 ..."
"$@" taas toimii kuin kaikki parametrit olisi yksitellen
suljettu lainausmerkkeihin:
echo "$1" "$2 "$3" ....
POSIX määrittelee seuraavat yleiset ympäristömuuttujat - ei vaadi että niiden pitäisi olla olemassa mutta jos ne ovat, niiden merkityksen pitää olla tämä:
Nuo ovat siis periaatteessa yhteisiä kaikille komennoille. Lisäksi yksittäiset POSIXin tuntemat komennot käyttävät seuraavia muuttujia:
CDPATH (cd), COLUMNS (ls), DEAD, MAILRC (mailx), IFS (sh), LPDEST, PRINTER (lp), MAKEFLAGS (make), OPTARG, OPTIND (getopts).
Näihin palataan tarkemmin myöhemmin.
POSIX määrittelee sh:n ei-interaktiiviseen toimintaan vaikuttaviksi vain muuttujat HOME, PATH, LANG, LC_ALL, LC_COLLATE, LC_CTYPE ja LC_MESSAGES, jotka on kuvattu edellä, sekä sh-spesifin muuttujan IFS.
IFS (Input Field Separators) määrittelee erotinmerkit syöttörivien lukemiseen ja parametrien ja komentokorvauksen tulosten kenttien erotteluun (siitä enemmän näiden yhteydessä). Oletusarvo on välilyönti + tab + newline (myös jos sitä ei ole asetettu lainkaan, mutta ei jos se on tyhjä).
POSIX.2 välttää ottamasta kantaa sh:n interaktiiviseen käyttöön, mutta luettelee kuitenkin seuraavat siihen mahdollisesti vaikuttavia muuttujia:
ENV FCEDIT HISTFILE HISTSIZE LINENO MAIL PPID PS1 PS2 PS4
Osa näistä vaikuttaa ainakin epäsuorasti skripteihinkin, joten palaamme niihin myöhemmin. (Ksh käyttää muuttujaa PS3 select-komennossaan.)
Muuttujien (ja parametrien) arvoon viitatessa niille voi samalla tehdä
joitakin testejä ja muokkaustoimintoja.
Yleinen syntaksi on
${varname oper [arg]}
eli ${}:n sisällä muuttujan nimen perään
lisätään operaattorimerkki
ja sen argumentti.
Seuraavat testaavat muuttujien olemassaoloa:
Kaikissa noissa kaksoispisteen voi jättää pois, jolloin ne hyväksyvät myös tyhjän muuttujan.
Seuraavilla voi muokata (tutkia) muuttujan arvoa, tai palauttaa vain osan siitä:
Positioparametrien käsittelyyn on kaksi erityiskomentoa (funktion sisällä nevaikuttavat funktion parametreihin):
shift [n]
hukkaa n ensimmäistä parametria ($0:aa ei lueta mukaan) ja siirtää seuraavia vastaavasti alkuun päin ($n:stä tulee $1 jne).
set [--] par1 ...
asettaa kerralla kaikki positioparametrit uusiksi. Rajoitin -- tarvitaan jos ensimmäinen parametri alkaa viivalla. (Näin siksi että set-komennolla on toinenkin tehtävä: sillä voi asettaa shellin optioita.)
Muuttujalle voi antaa arvon vain yhden komennon suorituksen ajaksi:
var=value command
Tällöin muuttuja asetetaan suoritettavan komennon ympäristöön mutta asetus ei jää voimaan komennon päätyttyä. (Poikkeuksena erityiset sisäiset komennot, joista myöhemmin enemmän.)
Bourne sh ja POSIX sen myötä tuntee vain yhdentyyppisiä muuttujia, merkkijonoja, joita sitten voidaan tarvittaessa tulkita luvuiksikin. Ksh88 tuntee erillisen kokonaislukutyypin, taulukot sekä joukon muita ominaisuuksia joita muuttujille voi määritellä. Ksh93 tuntee liukuluvutkin.
Muuttujille annetaan tyyppi komennolla typeset, jolla on melkoinen liuta optioita, seuraavassa tärkeimmät:
Taulukota puolestaan voi luoda komennolla
set -A nimi alkio1 alkio2 ...
tai alkioittain tyyliin x[0]=a, ja
taulukon alkioihin viitataan tyyliin ${x[a]}.
Alkioiden indeksointi alkaa nollasta ja yläraja voi
olla suhteellisen pieni (ksh88:ssa 1023).
Komentojen (mukaanlukien funktiot) syöttöä ja tulostusta voi ohjata seuraavilla tavoilla:
Ksh tuntee lisäksi seuraavat:
Huom. Tiedostokahvanumero n pitää erottaa edeltävästä tekstistä välilyönnillä tms, ja toisaalta sen ja siihen kuuluvan uudelleensuuntausmerkin välissä ei saa olla välilyöntiä. (Sen jäljessä, ennen tiedostonimeä, tyhjää saa olla muttei tarvita.) Vertaa seuraavia:
cat file22>foo cat file2 2>bar echo 1 2>foo echo 1 2 >bar
Tiedostonumeron yläraja on toteutuskohtainen, kuitenkin ainakin 0-9 toimivat aina, ja 0 (stdin), 1 (stdout) ja 2 (stderr) ovat valmiiksi auki.
Uudelleensuuntausmerkit tulkitaan ennen komentoa, niinpä ne voi sijoitella komentoriville melko vapaasti. Vertaa:
echo kala >fisu >fisu echo kala echo >fisu kala echo 4 + 2 > 5 - 3 echo 4 + 2> 5 - 3 echo 4 +2> 5 - 3 echo 4+2>5-3
Huom. erityiset sisäiset komennot ja varatut sanat voivat käyttäytyä poikkeavasti tässä suhteessa. Pääsääntöisesti uudelleensuuntaukset kannattanee sijoittaa komennon jälkeen.
Ns. here-document on erikoistapaus uudelleensuuntauksesta: se ohjaa syötön tulemaan skriptissä itsessään seuraavasta tekstistä rajasanaan saakka. Jos sana tai sen osakin on suojattu, teksti luetaan sellaisenaan, muussa tapauksessa tekstilaajennukset tehdään kuten tuplalainausmerkeissä. Lisäksi sanan alussa mahdollisesti oleva tavuviiva tarkoittaa sisennystä tab-merkeillä (ei välilyönnein).
Esim. Tulostetaan muuttujien X, Y ja Z nimet ja arvot:
cat <<EOF X=$X Y=$Y Z=$Z EOF
Komennon tulostuksen voi muuttaa merkkijonoksi komentorivillä kahdella vaihtoehtoisella syntaksilla:
Jälkimmäinen on jokseenkin aina parempi vaihtoehto, se on selkeämpi erityisesti useampia sisäkkäisiä korvauksia käytettäessä ja erikoismerkkien suojaussääntö sille on parempi.
Ksh (mutta ei POSIX) tuntee erikoistapauksena syntaksin $(<file), joka tekee olennaisesti saman kuin $(cat file) käynnistämättä uutta prosessia.
Komento
read [-r] muuttujalista
lukee yhden rivin stdinistä (jonka tietty voi uudelleensuunnata), ja purkaa sen $IFS:n sisällön rajaamiin kenttiin ja tallettaa tulokset listan muuttujiin. Jos muuttujia on liian vähän, kaikki loput kentät talletetaan viimeiseen, jos liikaa, viimeiset jäävät tyhjiksi. Jos rivi loppuu kenoviivaan, lukee seuraavankin rivin paitsi jos -r optio on annettu.
Esim. Mitä seuraava tekee? Miksi? Vertaa ksh:ta ja bashia.
echo a b | read x echo $x
Muuttuja IFS vaikuttaa syöttöön sen verran monimutkaisella tavalla, että se ansaitsee oman kappaleensa.
POSIXin mukaisissa shelleissä IFS vaikuttaa vain muuttuja- ja komentokorvauksen tulokseen, ei kuitenkaan tuplalainausmerkkien sisällä, sekä read-komentoon. Vanhemmissa shelleissä se saattaa vaikuttaa komentorivin tulkintaan muutenkin.
IFS:n eri arvot vaikuttavat seuraavasti:
echo x , y z |(IFS=' ,' read a b c; echo "a=$a,b=$b,c=$c") a=x,b=y,c=z
Huom. Tämä tuntuu olevan vaikea asia, etenkin viimeinen kohta; esim. bash ei osaa sitä ainakaan vielä versiossa 2.03. Yleensä ei kannattane käyttää IFS:ssä oletuksen lisäksi kuin yksimerkkisiä arvoja (ja sittenkin varautua siihen että tyhjiä hukkuu kuitenkin).
Lisää esimerkkejä:
x='1 + 2' expr $x IFS=: expr $x expr 1 + 2
Echo tulostaa merkkijonon stdout'iin. Sillä ei ole mitään siirrettäviä optioita: SysV:n ja BSD:n versiot olivat liian erilaisia että POSIXkaan olisi saanut niitä yhdistettyä.
BSD:n echo tuntee yhden option: -n, joka jättää rivinvaihdon tulostuksesta pois.
SysV:n echo ei tunne optioita mutta sen sijaan tulkitsee argumenteissaan olevia kenoviivoja seuraavasti:
Gnu-projektin echo toimii kuten BSD:n mutta tunnistaa lisäksi option -e, joka saa sen tulkitsemaan kenoviivan sysV:n tyyliin. (Gnu echo:n uudemmat versiot tuntevat muitakin optioita.)
Yleisesti echoa ei voi käyttää siirrettäväksi aiotussa skriptissä jos pitää tulostaa kenoviivoja, viivalla alkava rivi tai jotakin ilman rivinvaihtoa.
Ksh tarjoaa echon korvikkeeksi komentoa print. Se ymmärtää sekä BSD:n echo:n -n -option että samat kenoviivakonventiot kuin SysV:n echo, mutta ne saa pois päältä optioilla -r. Muista optioista mainittakoon -un, joka ohjaa tulostuksen tiedostokahvaan n, sekä -p, joka ohjaa sen co-prosessille.
printf format [arguments...]
tarjoaa muotoillun tulostuksen suunnilleen samalla tavalla kuin C:n printf() (liukulukutulostusta lukuunottamatta). Lisäformaattina %b ymmärtää samat kenoviivakonventiot kuin sysV:n echo. Formaateilla b, c ja s argumentti tulkitaan aina merkkijonoksi, muuten C:n mukaisesti.
Jos argumentteja on enemmän kuin formaatissa kenttämäärityksiä, formaattia käytetään uudelleen alusta.
Haluttaessa vähänkään monimutkaisempaa tulostusta, printf on ainoa edes kohtuullisen siirrettävä keino.
Seuraava: 4.6 Shellin jokerimerkit
Edellinen: 4.1-4.3 Skriptien suoritustavat, funktiot, erikoismerkkien suojaus