...josta mitkään ohjeet, man-sivut tai netissä olevat organisaatoiden super-virtuoosit eivät puhu...
Tuli mieleen joitakin asioita tuosta edellä olevasta. Pieni johdanto niin tästä on iloa ehkä muillekin...
Muuttuja joka on taulukko (engl. array)Jossain aiemmin kerroin että Bashin muuttujat ovat luonnostaan yksiulotteisia taulukoita --- jos käytät niitä sillä tavalla. Se mikä joissain muissa ohjelmointikielissä tunnetaan muuttujan tyyppinä määräytyy Bashissä hyvin yksinkertaisesti ilman mitään määritystä: Alat käyttää muuttujaa kuin se olisi taulukko ja se on sellainen. Mitä tuo sitten oikeastaan tarkoittaa ? Mainitsit tuolla sijoituslauseen joka on muotoa:
taulukko=( ...jotain...)
Tuossa =() -muoto kertoo Bashille että muuttujaan jolle keksin nimen "taulukko" halutaan tiputtaa sisään jotain monikenttäistä ja Bash alkaa tehdä "numeroituja laatikoita" peräkkäin alkaen numero nollasta eteenpäin eli itseasiassa meillä on sen jälkeen:
taulukko[0], taulukko[1], taulukko[2],..... taulukko[n]
eli indeksinumeroita on niin pitkälle kuin yksittäisiä asioita tuli tuolta sulkujen sisältä.
Jos haluat kurkistaa laatikkoon tai käyttää sitä johonkin niin et voi kirjoittaa pelkästään
$taulukko[0]
vaan aaltosulkujen kanssa
${taulukko[0]}
. Ja ne kaikki kentät yhdellä kertaa saa ilmauksella
${taulukko[@]}
sijoitettua eteenpäin, tulostettua tai mitä sitten halutaankin tehdä.
Ajatellaan pientä esimerkkiä tästä =() -asiasta:
teksti="kissa koira hevonen"
Tuossa meillä näyttäisi olevan kolme merkkijonoa joiden välissä on välilyönti. Tuossa muodossa tuo koko hoito on tuolla $teksti muuttujassa kuitenkin yhdessä ainoassa "laatikossa" eli jos ajatellaan sitä taulukkona niin indeksissä nolla. Eli jos tulostat sen niin
echo ${teksti[0]}
kissa koira hevonen
Oikeasti kyseessä onkin yksi merkkijono johon sisältyvät nuo välilyönnit eli tuo kaikki on yhtä kokonaisuutta.
taulukko=($teksti)
Tuo tiputtaa kunkin välilyönnillä erotellun sanan omaan säilöönsä (sen sijaan että ne olisivat kaikki yhdessä):
echo ${taulukko[0]}
kissa
echo ${taulukko[1]}
koira
echo ${taulukko[2]}
hevonen
Mutta: Millä perusteella Bash pätkii sen juuri välilyönnin kohdalta ? Vastaus on tuo "IFS" joka on yksi Bashin ennaltamääritetty muuttuja. Oletuksena se sisältää välilyönnin eli "SPACE 20h", Tab-merkin eli "TAB 09h" ja rivinsiirron "LF 0ah". Kurkataanpa vielä "hexdump -ohjelmalla":
hexdump -C <<< "$IFS"
00000000 20 09 0a 0a | ...|
00000004
Näyttäisi olevan.
Nyt herää kysymys jos haluaisinkin pätkiä jostain muusta kohdasta kuin välilyönnin tai tabin kohdalta. Tuo onnistuu kyllä yksinkertaisesti muuttamalla tuon IFS muuttujan arvon mutta: Hyvä tapa on tallettaa sen sisältö ennen kuin muuttelee ja palauttaa takaisin mitä se oli kun ei enää tarvita tätä muutettua asetusta. Ei ole suositeltavaa oikaista ja antaa "unset" sille lopuksi vaan tehdä talletus ja palautus. Tuo on selitetty tarkemmin edistyneissä Bash-oppaissa. Tyypillinen tallennus/palautus:
oldifs="$IFS"
...tehdään_jotain...
IFS="$oldifs"
IFS muuttujan käyttöön liittyy yksi mielenkiintoinen poikkeus jolloin sitä ei tarvitse erikseen tallettaa/palauttaa:
Jos IFS asetuksen jälkeen seuraa välittömästi samalla rivillä heti perässä joko komento tai funktio. Tällöin muutettu IFS sisältö on voimassa vain tuon komennon tai funktion ajan. Tuota näkee usein käytettävän "read" komennon + silmukan yhteydessä:
while IFS= read -r tiedostonimi; do
echo "$tiedostonimi"
done < tiedostonimiä_tiedostossa.txt
jolloin lukeminen ei epäonnistu jos tiedostonimessä on välilyönti tai useampikin.
Yksi hyödyllinen mutta harvemmin tunnettu ilmaisu Bashissä on
+=
eli "append" jossa alkuperäistä muuttujaa ei korvata vaan sen perään lisätään. Tuo "plus-yhtäläisyysmerkki" sijoitus toimii sekä tekstillä että taulukoilla. Sillä voi tehdä tekstin ketjuttamista peräkkäin mutta taulukoiden yhteydessä se on kätevä lisäämään taulukkoon uutta sisältöä. Tekstiesimerkki:
a=mäyrä
a+=koira
echo "$a"
mäyräkoira
ja taulukolla:
taulukko+=("kissa")
taulukko+=("koira")
taulukko+=("hevonen")
echo ${taulukko[@]}
kissa koira hevonen
Tuossa nuo menivät siis indekseihin 0, 1 ja 2 muuttujassa "taulukko". Bashissä on paljon erilaisia tapoja ilmaista asioita ja ne on dokumentoitu melko hyvin mutta silti sen oikean asian löytäminen voi olla joskus vaikeaa. Nämä taulukkoasiat (array) löytyvät täältä:
http://tldp.org/LDP/abs/html/arrays.htmlMuutenkin tuo on se opas jota koodaajat käyttävät hallitsevana dokumentaationa, alkusivu on tässä:
http://tldp.org/LDP/abs/html/Teksti-indeksin käyttö (associative array)On yksi tilanne jossa taulukko _täytyy_ myös Bashin tapauksessa määritellä ennakolta: Jos halutaan käyttää hieman erikoisempaa taulukkoa jossa taulukon solujen indeksit eivät ole numeroita 0, 1, 2,... vaan niille annetaan nimet (jotka voivat olla mitä vain haluat keksiä tilanteen mukaan). Tällöin sekä taulukkoon tallettaminen että sinne lisäys tapahtuu noiden nimi-indeksien avulla eli voidaan ajatella mielikuvana että tavarat ovat tallessa levällään omissa nimetyissä paikoissaan missä lienevätkin mutta nimi-indeksillä löytyy indeksinumeron asemasta. Ehkä postilaatikosto jossain taloyhtiössä kuvaisi sitä hyvin:
declare -A postilaatikosto
eli määrittelimme muuttujan "postilaatikosto". Lukumäärää ei tarvitse kertoa missään Bashin taulukossa, niitä laatikoita on aina se mikä tarvitaan.
Tiputetaan jotain noihin postilaatikoihin nimi-indeksillä:
postilaatikosto[Nieminen]="myyntikirje"
postilaatikosto[Mattila]="karhukirje"
postilaatikosto[Sievänen]="rakkauskirje"
postilaatikosto[Matti Nykänen]="suksiesite"
ja tulostetaan koko laatikosto:
echo ${postilaatikosto[@]}
myyntikirje karhukirje rakkauskirje suksiesite
Pieni mielenkiintoinen yksityiskohta: Indeksi voi olla monisanainenkin tai aika mielivaltainen merkkijono, tuossa oli indeksinä "Matti Nykänen" eli skanditkin kelpaavat. En ole tutkinut aiheuttaako välilyönti indeksin nimessä jossain yhteydessä kiusaa.
Tekisikö mieli kurkistaa mitä tapahtuu jos laittaakin numeron nyt indeksiksi ? Mitä mahtaisi tapahtua ? No ei oikeastaan mitään hyödyllistä sillä: Numero 0, 1, 2... ei nyt olekaan numero --- vaan nimi. Ei löydy mitään tuolta nimillä "0" tai "1".
Koko taulukko tyhjenee:
unset postilaatikosto