Joo, Bash roikkuu vielä pitkään mukana Linux-jakeluissa. Applen macOS:ssä tosin vaihdettiin jo oletus-shelliksi Bashia edistyneempi ja monipuolisempi Zsh, joten se on käyttäjämäärältään ohittamassa Bashin. Ehkä osa Linux-jakeluista seuraa perässä tulevina vuosina. Zsh ei ole ihan nuori vaihtoehto sekään. Ensimmäinen versio on julkaistu vuonna 1990, eli vain vuosi Bashin ensimmäisen version jälkeen ja ennen Linuxin tuloa.
Kaikkea hyvää Zsh:lle sillä onhan BASH:issa paljon parannettavaa - mutta minä olen liian ryytynyt tapoihini siirtyäkseni Zsh:ta käyttämään.
Mutta hyppäsiköhän Apple sittenkin väärään junaan sillä kyse ei taida olla kielen kyvykkyydestä vaan sen käyttäjien asenteista - laulun sanoin: lökäpöksyni mun.
Enkä edes välitä siitä kuinka nopeasti skriptini toimivat huolimatta siitä että ajoitan ne aina - koska sehän taitaa kertoa mihin suuntaan kehitys on menossa - nopeampi ei oikeastaan ole parempi mutta hitaampi on varmasti huonompi. Mutta kyvykkyys sensijan kiinnostaa paljonkin. Ja päinvastoin kuin väitetään niin BASH:ilta tuntuu onnistuvan 'mikähyvänsä' - enkä tosiaan käsitä kuka sen kyvykkyyttä yrittää kätkeä. Tosin kaikki toimii hyvin hankalasti sillä eihän ongelmia kauan sitten ratkaistu ollenkaan samallatavoin kun nykyään - mutta paljolti samoja ne ongelmat olivat aikoinaan kuin nykyäänkin. Ja koodin pituushan ei kerro koodin nopeudesta paljoakaan vaan pidempi on useinkin nopeampi.
Mutta valitettavasti kaikki ponnistukseni menevät hukkaan sillä BASH:in kirjastojen toimimisen haittaaminen tuntuu olevan virtuooseille pyhä sota - ja kirjasto-kamaa kaikki edistyneempi on ja mikäli se ei kirjastoon päädy niin unohtuuhan se aikanaan.
***
Olen aina ihmetellyt niitä postauksia joita BASH skripteistä kirjoitetaan. Esimerkki on ulkomaisilta verkkosivuilta - sillä minä en maailmalle kirjoittele vaan poikkeuksetta ainoastaan luen.
Käytännössä tapahtumat seuraavat toisiaan melkein aina seuraavalla tavalla: jollain ulkomaan verkkosivulla esitetään ongelma ja sille tulee esimerkiksi sata erilaista vastausta. Ensimmäiset vastaukset ovat tottakai vähän avuttomia mutta jo esimerkiksi kymmenes ratkaisee ongelman erittäin nopealla ja kaikissa tilanteissa toimivalla tavalla. Luulisi että vastukset loppuisivat siihen mutta niin ei koskaan käy vaan kelvottomien ratkaisujen tulva vain kiihtyy. Täytyy oppia etsimään se paras vastaus kaikista postauksista sillä se paras vastaus ei yleensä ole viimeisten joukossakaan. Olenkin alkanut epäillä että asioita sotketaan tahallisesti - tai sotkettiin silloin kauan sitten.
***
Seuraavista 'mahdottomista skripteistä' pikkuisen: nimi-parametrithan eivät kuulemma toimi BASH:issa? Tässä ne toimivat. Vertailun vuoksi esitän toiminnan käyttäen arvo-parametrejakin.
Tarkoituksena on tehdä skripti joka etsii maksimin/minimin silloinkin kun joukossa on desimaalilukuja. Aluksi täytyy kuitenkin kertoa kuinka desimaaalilukuja muodostetaan BASH:issa sillä kyllä BASH:in jotkut käskyt osaavat senkin ihan kikkailematta. Esimerkiksi anna käsky:
seq -s' ' 12600 -1.1234 1.1 | tr , .
- seq noudattaa printf:n muoto-määräyksiä joten esimerkiksi seq laitaa tulostuksessaan Suomessa pilkun desimaalieroittimeksi. Jos se on alunperinkin piste niin tr on vain turha mutta virhe se ei silloinkaan ole.
- muuten seq toimii kaksimielisesti: se vaatii aina käskettäessä desimaalipistettä vaikka se antaisikin sen pilkkuna ulos.
Tämän avulla saa tehtyä sellaisen desimaaliluvuista muodostuneen matriisin jonka arvot ovat satunnaisessa järjestyksessä (ja jossa on jäseniä 11215 eli yhtämonta kuin edellisessä minimin määrittelyssä joka siis kesti 7 sekuntia):
sort -R <(seq -s' ' 12600 -1.1234 1.1 | tr ' ,' '\n.' )
seuraavaksi muodostetaan lauseen avulla matriisi ja etsitään siitä pienin arvo:
unset apu # skriptin esimmäiseksi käskyksi täytyy kirjoittaa: unset apu. Sillä kun matriisi on määritelty jää se päätteen muistiin kunnes se tuhotaan käskyllä unset tai siirtytään toiseen päätteeseen - ja ellei unset:iä ole tulee sotkua kun määritelään apu uudelleen. Unset ei ole virhe vaikka matriisia ei vielä olisikaan.
apu=$(sort -R <(seq -s' ' 12600 -1.1234 1.1 | tr ' ,' '\n.' ))
# etsitään maksimi/minimi hakemalla matriisin arvot BASH:in kirjanpidosta nimi-parametrin avulla. Tämä on nopein menetelmä
function haeminimi () { sort -n <(declare -p $1) | tr -dc '\n'[.0-9] | head -2 | tail -1 ;}; time haeminimi apu # selitys käskyille: | head -2 | tail -1 -> valitaan rivi 2
function haemaksimi () { sort -n <(declare -p $1) | tr -dc '\n'[.0-9] | tail -1 ;}; time haemaksimi apu
# tai etsitään maksimi/minimi ratkaisten matriisin arvot käyttäen käskyä: 'eval nimi-parametri' (mutta eval on jostain syystä virtuoosien kiroissa)
# apu on tässä esimerkissä nimi-parametri mutta siinähän voisi olla minkä matriisin nimi hyvänsä:
function haeminimi () { sort -n <(eval echo \${$1[@]} | tr ' ' '\n' ) | head -1 ;}; time haeminimi apu
function haemaksimi () { sort -n <(eval echo \${$1[@]} | tr ' ' '\n' ) | tail -1 ;}; time haemaksimi apu
# tai hetaan maksimi/minimi käyttäen arvo-parametreja:
function haeminimi () { sort -n <(echo "$*" | tr ' ' '\n') | head -1 ;}; time haeminimi "${apu[@]}"
function haemaksimi () { sort -n <(echo "$*" | tr ' ' '\n') | tail -1 ;}; time haemaksimi "${apu[@]}"
- näissa esimerkissä matriisin nimi on apu, mutta funktiot toimisivat samoin vaikka matriisin nimi olisi joku muukin
- ja nopeus on tosiaan kaiklla monisatakertainen siihen vertaavaan menetelmään verrattuna - ja toimitaan aina samalla tavalla riippumatta siitä millaista data on eikä milloin mitenkin niinkuin siinä hitammassa vertailussa joka tukehtuu jo desimaali-pisteeseenkin.
- muuten: BASH:issa ei kovin nopeasti pidä hyväksyä laskua oikeelliseksi vaikka se tuntuisikin toimivan. Samat testit tulee suorittaa eri päivinä kun kone on ollut välillä sammutettuna ja tehdä erilaisia testejä monta päivää - testejä samassa pääteistunnossa ja välillä vaihtaen pääteistuntoa, joskus tarkoin määritellyllä datalla ja joskus satunnaisella datalla, käännellen-väännellen ja välituloksia ottaen .... joten parin viikon kuluttua samasta aiheesta testin tekemisen ajatteleminenkin aiheuttaa paiseita ja on tehtävä välillä jotain muuta.