iki-vanhojen tekstinkäsittely-käskyy ovat uusia käskyjä yli kymmynen kertoo nopeampia ja koska tulkki tykkää niistä niin joukkona niiden nopeus nousee edelleen. Siis kuka pääkallon-paikan suurista virtuooseista hylkäsi nuo vanhat käskyt niin ihan yksin hän hidasti BASHa yli kymmenkertaisesti, teki desimaalilaskennan mahdottomals, esti nimi-parametrien käytön ja parrametrien palauttamisen.... - ja samalla älytti virtuooseja niin pahasti että nämä mieluummin antoivat BASH:in tuhoutua kuin tunnustivat että heitä oli älytetty.
Potenssiin korottamisen funktiossa noide käskyjen nopeuden taas kerran huomasin - tässä tapauksessa laskussa: -1.234567890123 ^ 10 - edes noin tarkoista laskuista ei normaali-komennoilla voi uneksiakaan. Nimittäin tuollaisia laskuja laskevan funktion vanhassa toteutuksessa sen 50:stä lauseesta yksi oli uusmuotinen koska en aikoinaan tiennyt että sillekin löytyy korvaava tekstijono-komento - silloin lasku kesti 15 ms. Kun sen yhden komennon muutti tekstijono-komennoksi niin koko funktion nopeus nousi viisinkertaiseksi elikä 3ms:iin. BASH:iksi nopeus on vallankumouksellinen - mutta on vielä liian aikaista tehdä mitään tarkempia johtopäätöksiä.
- funktio löytyy paikasta:
https://forum.ubuntu-fi.org/index.php?topic=303.msg447967#msg447967---
Desimaalilukujen kertolaskussa tuloksen numerot tulevat oikein kun desimaalipisteen poistaa sekä kertojasta että kerrottavasta ja suorittaa kertolaskun senjälkeen - joten lopputulos on täysin oikea jos siihen saa sijoitettua desimaalipisteen oikealle paikalle. Tämän oikean paikan laskeminen on yksinkertaista. Mutta numeroiden käsittelyssä on ehdottomasti käytettävä yksinomaan tekstijono-komentoja - varsinaiset kertolaskut kylläkin suoritetaan BASH:in kokonaisluku kertojassa.
Koska tuloksen täytyy yksinkertaisessa versiossa mahtua 18 numeroon niin kerrottavat luvut voivat olla korkeintaan 9 merkkisiä. Koska tarkkuus jäisi tällöin kovin vaatimattomaksi käytetään kaksinkertaista tarkkuutta joten sekä kertoja että kerrottava voivat olla 18 merkkisiä liukulukuja jolloi tulos voi olla 32 merkkinen liukuluku. Kansakoulu tasoista matematiikkaa kaksinkertainen tarkkuuskin on.
Kerro18 löytyy esimerkiksi paikasta
https://forum.ubuntu-fi.org/index.php?topic=303.msg448022#msg448022- jos haluat kokeilla sitä niin leikkaa sen koodikenttä kokonaisuudessaan, liimaaa se päätteeseen ja paina enter
- voit antaa nyt laskuja itsekin - esimerkiksi kirjoita: kerro18 12345678.87654321 87654321.12345678
- desimaalisten liuku-lukujen kaikki muutkin perus-laskutoimitukset toimivat jo silloin kun BASH oli ihan nuori. Virtuoosit eivät vain osanneet kasata niiden funktioita - kyse on tiedosta että ne voi tehdä kuten kuvattiin - eikä taidosta sillä laskut ovat yksinkertaisia.
- eihän tämmöisillä nykyään mitään arvoa nykyään ole mutta silloin kun BASH:ia alettiin romuttamaan ne olisiva olleet BASH:issa tarpeen. Ja kuka tietää onko tämä vaihe vasta alkua? Onko tämäkin kieli joka ei suostu kuolemaan?
- pahin vaikeus laskussa on löytää oikeat tekstijono-komennot sillä BASH-raamatussakin on vain muutama. Tuntuu tosiaan siltä että parhaat komennot on heitetty roskikseen jotta desimaali-laskuja ei voisi tehdä ja BASH:ia voisi mollata paremmin.
- tietokoneiden matematiikka-prosessoritkin aikoinaan toimivat kertolaskussa aikoinaan samoin kuin kerro18.
---
Aina kun skripti toimii - ja silloinkin kun on toimimatta - niin BASH vaanii monia tapahtumia - matematiikka-skriptissä näitä kahta asiaa:
1. koettaa löytää skriptirivin ensimmäistä sanaa massamuistin $PATH nimisen muuttujan osoittamista kansioista senjälkeen kun on lauseen lopussa painettu enter - niissä kansioissa olevat tiedostot on nimetty käskyjen nimillä. Kansiot käydään läpi siinä järjestyksessä missä ne on annettu muuttujassa $PATH - ja sitä käskyä käytetään joka ensiksi löytyy sillä useissakin kansioissa voi olla sama käsky toteutettuna hieman eritavalla - ja jos kirjoittaa käskyyn polunkin niin käytetään sitä käskyä.
- luettelon koneesi ohjelmakansioista saat kun kirjoitat: echo $PATH. Sen tulostuksessa merkki : on erote-välilyönti - sillä vaikka tiedostonimessä on harvoin välilyöntejä niin merkkiä : ei voi olla koskaan. Ja:
A. jos nimi löydetään jostakin noista kansioista niin sen osoittama tiedosto suoritetaan ja kaikki sanan perään kirjoitetun oletetaan olevan käskyn tarkentimia elikä 'kytkimiä' mikäli niiden edessä on miinusmerkki ja muuten toiminnan kohdetta. Jos kohteen ensimmäinen merkki voi olla miinus-merkki niin sellaisen kohteen eteen tulee kirjoittaa -- .
- toiminnan tulos tulostetaan kuvaputkelle ellei toisin ole määrätty.
- muuten se löytyvä ohjelma on harvoin BASH-muotoista vaan yleensä ne ovat käännettyä C:tä. Siten BASH:in käskyt ovat yleensä ällistyttävän nopeita - vain skripti kokonaisuudessaan on ällistyttävän hidas - ja hitautta lisää se että skriptit tehdään niin että tulkkia kutsutaan jokaisen käskyn jälkeen. En ole saanut tarkasti selville kuinka kauan tulkin kutsuminen kestää mutta jotain .5 ms se on.
B. jos nimeä ei löydetä niin koetetan löytää sana määritellyistä funktioista
- listan koneesi määritellyistä funktioista saat käskyllä: declare -f . Niitä on jokaisessa koneessa alussa nin 74.
- funktio on normaali skripti joka on kirjoitettu funktiomuotoon: function funktion_nimi { funktion lauseet yksi- tai monirivisenä täysin normaalina skriptinä }
- huomaa {} sulut funktion koodin ympärillä - niitä käytettäessä ei luoda uutta istuntoa ja seurauksena siitä funktio-kutsu kestää vain noin 50mikrosekuntia ja muutujat ovat yhteisiä 'pääohjelmassa' ja funktiossa - siis jos muuttujaa muutetaan toisessa niin se muuttuu toisessakin. Funktiossa voidaan kuitenkin määrätä muuttujan arvon muutoksien kuuluvan vain funktioon - määreellä: local muttujan_nimi
- funktion ympärillä voi olla myös kaarisulut jolloin luodaan uusi istunto. Se kestää paljon kauemmin ja sillä on myös omat muuttujat. Ei tällaisia funktioita käytännössä ole näkynyt - mutta asia on kuitenkin hyvä tietää.
- funktiokutsu voi olla sana, esimerkiksi: function koe () { echo $1 ;}; koe jees pox limited. Sana koe on se kutsu - ja myös funktion nimi - ja jees kutsun ensimmäinen parametri. Koska jees on ensimmäinen parametri niin funktiossa se nimi on $1. pox on toinen parametri joten se on $2. limited on kolmas parametri elikä $3.
- funktiokutsussa () on merkkinä siitä että parametreja on - monessa paikassa BASH merkitsee säilytyspaikkaa noin - tai yleensä {}.
- funktiokutsu voi olla myös muuttujan sisältö: function koe () { echo $1 ;}; a=koe; $a jees
- funktiokutsu voi olla myös matriisin nimi tai sisältö ja jopa assisiatiivisen matriisin ja silloin pompun osoite on koodi-muunnettu. Parametreja voi olla kuinka monta vaan eikä niiden tyyppiäkään rajoiteta mitenkään - ne voivat olla myös käskyjä, funktioita ja regex:iä - ne ovat kylläkin vaikeakäyttöisiä.
- funktio voi kutsua mielivaltaisen monia toisia funktioita tai jopa itseään - itseään kutsuvassa funktiosta täytyy löytyä ehto milloin itseä ei enää kutsuta. Funktioketjun pituudelle ei ole tiukkaa ylärajaa. Eikä funktio-nimille juurikaan ole rajoituksia - olemassa olevien käskyjen nimiä kannattaa välttää mutta pakko sekään ei ole ja sellainen funktio korvaakin käskyn - sillä ainoastaan viimeistä määrittelyä käytetään - ja funktion alkuperäinen määrittely palaa voimaan kun pääte suljetaan.
- minkäniminen funktio tahansa voidaan määritellä uudelleen vaikka kuinka useasti ja vain viimeistä määrittelyä käytetään. Uudestaan määrittely ei oikeastaan hidasta mutta muistiahan se vie koska BASH:issa ei automaattista roskankeruuta juurikaan ole - voit kyllä tehdä oman roskankeruu-funktion ja ajaa sitä silloin-tällöin. Samasta syystä todella isojen matriisien uudestaan määrittely on ongelmallista ellei ensin tuhoa matriisin vanhaa määrittelyä käskyllä: unset matriisin-nimi.
-jos nimeä ei löydy määritellyistä funktioistakaan niin suoritetaan funktio: command_not_found_handle ja tehdään mitä se määrää - normaalisti tulostetaan 'commad not found' mutta voisihan sensijaan kutsua muita funktioita. Command_not_found_handle niminen funktio on jokaisen koneen päätteessä aina toiminnassa - katso millainen koneessasi on käskyllä: declare -f command_not_found_handle - se on kaikinpuolin ihan normaali funktioksi kirjoitettu skripti. Muuten tulostamatta jättäminen ei ole sama kuin tulostaa tyhjää joten täytyy kirjoittaa echo '' . Funktiossa on pakko tehdä jotakin tai virhe seuraa - ja esimerkiksi ehdollinen luse joka ei toteudu ei myöskään tee mitään ja siitä tuleekin pottumainen virhe.
- command_not_found_handle niminen funktio on jokaisen koneen päätteessä aina määriteltynä - katso millainen koneessasi on käskyllä: 'declare -f command_not_found_handle' - se on kaikinpuolin ihan normaali funktioksi kirjoitettu skripti. Muuten tulostamatta jättäminen ei ole sama kuin tulostaa tyhjää joten täytyy kirjoittaa echo '' . Funktiossa on pakko tehdä jotakin tai virhe seuraa - ja esimerkiksi ehdollinen lause joka ei toteudu ei se myöskään tee mitään ja siitä tuleekin pottumainen virhe.
- matematiikka-skriptissä command_not_found_handle on määrätty tulostamaan tyhjää - itseasiassa määrätään uudelleen määritelty command_not_found_handle tulostamaan tyhjää - se jonka pitäisi udella: tarkoititko käskyä xxx paketissa yyy
- minkäniminen funktio tahansa voidaan määritellä uudelleen vaikka kuinka useasti ja vain viimeistä määrittelyä käytetään. Uudestaan määrittely ei oikeastaan hidasta mutta muistiahan se vie koska BASH:issa ei automaattista roskankeruuta juurikaan ole - voit kyllä tehdä oman roskankeruu-funktion ja ajaa sitä silloin-tällöin. Samasta syystä todella isojen matriisien uudestaan määrittely on ongelmallista ellei ensin tuhoa matriisin vanhaa määrittelyä käskyllä: unset matriisin-nimi.
- tässä command_not_found_handle on määrätty tulostamaan tyhjää - itseasiassa määrätään uudelleen määritelty command_not_found_handle tulostamaan tyhjää - se jonka pitäisi udella: tarkoititko käskyä xxx paketissa yyy.
---
2. Käskyllä:trap BASH on määrätty virheen sattuessa suorittamaan komento: 'laske "$BASH_COMMAND"'.
- se määrää että virhetilanteessa suoritetaan funktio:laske käyttäen sen parametrina muuttujaa nimeltä: "$BASH_COMMAND" (se on BASH:in itsensä tekemä muuttuja ja sen voi vain lukea muttei kirjoittaa normaalilla tavalla - esimerkissä muuttujassa on se näpytelty teksti: 1+1. Tästä syystä näpytellyssä tekstissa ei saa olla kaarisulkuja vaan on käytettävä hakasulkuja.)
- huomioi muuten että myös se funktio command_not_found_handle toimii ja saattaa kirjoittaa: command not found. Laskenta kuitenkin alkaa mutta koska BASH on hidas saattaa näyttö pysyä muuten tyhjänä kauankin joten täytyy olla kärsivällinen - kyllä se tuloskin joskus tulee.
---
Käytännössä kohdattavia muita trap-komentoja:
trap 'echo virherivi:${LINENO[@]}; echo funktiossa:¨${FUNCNAME[@]}" ; read' ERR
trap 'rc=$?; echo "virhekoodi $rc rivillä $LINENO-${FUNCNAME[0]}" ' ERR
trap ' (( $? )) && echo ${FUNCNAME[0]}" palautti virheen:"$?' RETURN
trap "echo kutsupino: ${FUNCNAME[@]}" ERR # kun funktiot kutsuvat toisiaan niin kerrotaan ne funktiot joiden kautta virheeseen päädyttiin.
trap pomppaaTänne SIGINT # mitä tehdään kun painetaan CTRL-c
trap 'echo "Control-C disabled."' 2
trap jälkiensiivous SIGTERM # kun skripti loppuu tai tekee suoritusaikaisen virheen mennään fumktioon: jälkiensiivous
trap 'echo "VARIABLE-TRACE> \$variable = \"$variable\""' DEBUG # muuttujan arvon seuraaminen
set -x; trap "echo hit_return;read x" DEBUG # käskyrivien suoritus yksi kerrallaan