Näytä kirjoitukset

Tässä osiossa voit tarkastella kaikkia tämän jäsenen viestejä. Huomaa, että näet viestit vain niiltä alueilta, joihin sinulla on pääsy.


Viestit - petteriIII

Sivuja: [1] 2 3 ... 33
1
BASH:ista haluttiin päästä eroon jo ennenkuin Ubuntusta tuli ensimmäinen versio. Syy siihen oli sama kuin miksi huippu-kyvykäs assembler-kieli tapettiin aikoinaan: skriptit olivat sillä liian kalliita tehdä ja ylläpitää (se hinta maksettiin kylläkin yleensä vain koodaajan selkänahalla). Lisäksi koodarien uusi sukupolvi toi mukanaan uusia parempia kommervenkkejä hyläten kaiken vanhan. Muisa kielissä muutaman vuoden jälkeen alettiin hyväksyä jotakin siitä vanhastakin - mutta BASH:issa ei palattu osittainkaan vanhaan vaan jäätiin täysin siihen uuteen. Lisäksi silloin kauan sitten useimmat hoitivat tietokoneitaan itse ja ainoastaan siinä tehtävässä BASH on huippuhyvä. 

Mutta BASH:ia ei voitu tuhota kerta-runttuulla niinkuin assembleria vaan se täytyi kiduttaa hitaasti hengiltä - ja mikäs tähän on sopivampaa kuin edistää tapoja tehdä skriptestä hieman avuttomia sensijaan että opetettaisiin tapoja tehdä nopeita ja kyvykkäitä - ja nimenomaan jokavaiheessa täytyi tuoda esiin BASH:in surkeus. Sitä en osaa sanoa uskovatko nykyiset virtuoosit noihin väitteisiin mutta se on varmaa että aikoinaan -eivät- uskoneet vaan puhuivat palturia ihan tieten.

Kun aloin tutkia BASH:ia silloin kun ensimmäinen Ubuntu tuli - aluksi pintapuolisesti ja lopussa kokopäiväisesti kun alkoi olla varmaa että virtuoosit esittävät teoriat siten että ilman johdatusta skriptaajat varmasti valitsevat kahdella tavalla tulkittavasta teoriasta sen väärän vaihtoehdon. Esimerkiksi sanotaan: BASH:in matematiikkamoottori ei desimaaleja hanskaa eika BASH:issa ole desimaali lukutyyppiäkään - kumpikin väite onkin kiistaton totuus - mutta noista tosiasioista skriptaajat ilmanmuuta tekevät sen väärän johtopäätöksen ettei BASH desimaalilaskuja osaa laskea. Se kyllä kiinnostaa ovatko 'advanced guidet' uskoneet myös - minä en usko kaikkien oppineiden ammatti-ohjelmoijien syyllistyneen moiseen sillä esimerkiksi vuosia sitten peräti verkkosivulla https://www.anandtech.com/ asia selvitettiin maallikollekin ymmärrettävällä tavalla - nykyään silläkään verkkosivulla ei ole edes halua perusteita selvittää, ei niitä monikaan halua lukea eikä varsinkaan niiden lukemisesta maksaa. Sensijaan lierot maksaa siitä ettei asioista kerrottaisi - mainostuloiksi väittävät.

Yhteenvetoa BASH:in mustamaalaamisesta:

1. Sen aiheuttaminen ettei kukaan ole yrittänytkään suorittaa desimaalilaskuja. Nopeat desimaalilaskut ovat aivan välttämättömiä jotta kieli menestyisi.
2. 'Kirjastokielto'. Kirjastot ovat nekin aivan välttämättömiä - ei niitä tosin voitu estää käyttämästä sillä kirjasto-käsite kuuluu BASH:in perus-palikoihin - mutta mustamaalata niitä voitiin ja poistaa kirjasto-osoitin.
3. Väite että funktioiden nimiparametrit eivät toimi. Ilmanmuuta ne toimivat, mutta niiden saaminen käyttöön vaatii oikeita taikasanoja - ja ainoa mitä virtuoosit voivat puolustustukseen sanoa etteivät he tunteneet yhtäkään noista monista taikasanoista - mutta sitä ei kukaan usko sillä niitä löytyy myös kokeilemalla - eikä mahdollisia käskyjä ei ole kovin montaa.
4. Nopeiden käskyjen piilottaminen. Nopeat käskyt eivät ainoastaan ole 10-kertaa nopempia kuin uudet vaan yksinomaan nopeista käskyistä kootut funktiot tulkataan kerralla jolloin nopeus-hyöty on vielä suurempi. Kyllä uusissakin käskyissä paljon hyvää on mutta useimmien ne yrittävät ratkaista sellaisia ongelmia joita ei käytännössä kohtaa - ehkäpä ongelma onkin vain se ettei kehdata myöntää että tuli hölmöiltyä ja nyt täytyisi alkaa taas käyttämään niitä vanhoja - ei tosiaan ainoa kerta kun on hölmöilty tällä samalla tavalla.
5. eval-käskyn 'kieltäminen' - mutta BASH:in omassa ~/.bashrc-tiedostossa on tällähetkellä kolme eval-käskyä joten BASH:in kehittäjät eivät virtuoosien väitteitä usko.
6. Saatu kaikki uskomaan että BASH tarvitsee aina ensimmäiseksi rivikseen käskyn: #!/bin/bash tai että skriptistä täytyy tehdä tiedosto jolle ehdottomasti tåytyy antaa suoritus-oikeus - tai että skriptin käskyt kirjoitetaan aina kukin omalle rivilleen - tai ehtolauseet peräti useammalle. Varmaan niin on parasta tehdäkin kun aloittaa skriptaamisen mutta voisi sentään edes vihjata että ei niin kannata jatkossa toimia kuin hyvin harvoin. Paitsi ehkä wintoosassa ja semmoisissa.

- tottakai kaikkeen on myös ihan kunnollisia syitä - esimerkiksi tietokonehan on aina turvallisuusriski ja vanhentuvat ohjelmat eritoten. Asioita tosin painotetetaan ihan ihmeellisesti.
- tarkoitus saattoi siis olla hyvä ja ettei vaan tajuttu mitä tuhottiin. Mutta eipä ollut ainoa kerta kun huonompi voittaa parempansa. Tällähetkellä BASH on kylläkin sotkettu niin syvälle suohon  ettei se varmankaan voi nousta sieltä koskaan.

2
BASH:in muisti on globaali - elikä jokainen muuttuja jonka arvoa muutetaan jossakin muuttuu kaikkialla muuallakin: mitä pääohjelmassa tehdään vaikuttaa kaikissa funktioissakin - ja mitä funktioissa tehdään näkyy pääohjelmassa ja toisissa funktioissakin - on kyllä parikin harvoin käytettyä tapaa eristää funktio - eli tehdä hiekkalaatikko, se on jo BASH:in idea tai vieläkin vanhempi - mutta niistä myöhemmin. 

Siis jos viitataan eri paikoissa saman nimiseen muuttujaan niin viitataan varmasti samaan muuttujaan - tässä täytyy painottaa että sama tekstijono voi toisessa paikassa olla muuttuja ja toisessa paikassa vain tekstijono - siis kun määrätään: echo $tekstijono niin yhdessä paikassa tulos voi olla jotain_ muuta _kuin_0 ja toisessapaikassa 0. Jos siis halutaan tehdä jossain funktiossa temppuja saman nimiselle muuttujalle jokakerta niin parametreja ei silloin tarvita ollenkaan - jopa se () voidaan jättää funktiokutsusta pois - tosin ei siitä ole haittaa jos sen kirjoittaa:
Koodia: [Valitse]
function koe { echo $a ;}; unset a; a=543; koe $a #-> tulostuu 543
function koe { a=543 ;}; unset a; koe a; echo $a #-> tulostuu 543
- 'unset muuttuja' ainoastaan palauttaa muuttujan arvoksi tyhjän - siis antaa sille saman arvon joka sillä on avattaessa pääte, elikä: ''. Muuten sotkisi se että BASH ei nollaa muuttujiaan ohjelmansuorituksen lopuksi vaan ainoastaan senhetkisen pääteistunnon lopuksi - siis pääteistunto on isä ja kaikki muut sen mukuloita - päätteellä on muuten myös määre: #!/bin/bash ja suoritusoikeuskin eivätkä sen mukulat niitä enää yleensä tarvitse.
- voihan käskyn unset jättää poiskin ja avata jokaisen käskyn suorituksen alussa uusi pääte.
- muuttujalle annettu arvo siirtyy toiseen skriptiinkin ellei päätettä välillä sammuteta - jos ei tiedä että näin tapahtuu on skriptaaminen tuskallista koska skriptit näennäisesti tekevät mitä sattuu.
- funktiossa voidaan muuttuja määritellä paikalliseksi - siis vaikka jossain muualla olisi saman-niminen muuttuja ei funktion muuttujan muuttaminen vaikuta siihen. Pääohjelmassa ei voida määritellä paikallisia muuttujia.

Jos halutaan jossain funktiossa tehdä samat temput mille muuttujalle/muuttujille tahansa nimestä välittämättä niin siirretään muuttuja normaalisti arvoparametrina.
- vain nimiparametri on palautettavissa missähyvänsä kielessä - arvoparametrin palauttamisesta puhuminen on todella himmeää - ei yksikään virtuoosi saisi moiseen puheeseen syyllistyä.
- nimiparametreja ei aikaisemmi osattu käyttää sillä kun funktioon siirretään muutujan nimi niin välittömästi siirron jälkeen se on vain tekstijono joka ei viittaa mihinkään. Se täytyy erikseen käskeä viittaamaan johonkin arvoon tai arvojoukkoon. Kuinka se tehdään yritetään seuraavassa kertoa niin että jokainen saisi selityksestä selvää:
Koodia: [Valitse]
arvoparametri: function koe () { echo $1 ;}; unset a; a=543; koe $a  -> tulostuu: 543  (tämä on se toiminne jota normaalisti käytetään )
nimiparametri: function koe () { $1=543 ;}; unset a; koe a; echo $a -> tulostuukin: =543: command not found . Mutta kyllä funktio toimii oikeinkin pienin muutoksin:
1. numeromuuttujalla:
Koodia: [Valitse]
function koe () {  let $1=543  ;}; unset numero; koe numero; echo $numero
2. tekstijonomuuttujalla:
Koodia: [Valitse]
function koe () {  read<<<höh $1  ;}; unset tekstijono; koe tekstijono; echo $tekstijono
3. matriisilla:   
Koodia: [Valitse]
function koe () {  < <(echo -e 1\\n2\\n3) readarray $1  ;}; unset matriisi; koe matriisi; echo ${matriisi[*]}
   
- hommassa on monia salahautoja; esimerkiksi jos kirjoittaakin <(echo 1 2 3) niin ei muodostukaan matriisia vaan tekstijono - ja tuo matriisi-vai-tekstijono on vaikeasti havaittava tilanne joka saa skriptaajan repimään pelihousunsa - eikä varsinaisesti virhe vaan joskus harvoin jopa toivottua - mutta normaalikäytössä senjälkeen mikään ei tunnu onnistuvan - yksi keino tilanteen havaitsemiseksi on kirjoittaa:
Koodia: [Valitse]
echo ${matriisi[0]}
joka tulostaa vain jäsenen nolla (siis katsotaan muuttuuko tuloste tilanteesta:
Koodia: [Valitse]
echo ${matriisi[*]})
Tai voisihan matiisin tulostaa niinkin kuin matriisi oikeastaan pitäisi tulostaa, joko:
Koodia: [Valitse]
printf "%s\n" "${matriisin_nimi[*]}"    tai: echo -e ${matriisin_nimi[*]/#/\\n}
- mutta eihän tuommoisia rotlia viitsi aina kirjoittaa ja monirivinen tulostekin on epämiellyttävä.

- vaikka nimiparametrit voisikin palauttaa niin parametrien palauttaminen olisi BASH:issa silkkaa ajanhukkaa - ja siksi BASH ei parametrien palauttamista edes osaa. Tehty hommahan tämä  väärinkäsitys on joten virtuoosit ovat täysin varmasti sen aikoinaan tunteneet ja sitä käyttäneetkin.
 
- kun virtuoosit havaitsivat että:
Koodia: [Valitse]
eval \$$1
palauttaa myös viittaukset niin heille tuli kiire vakuuttaa että BASH:issa käsky eval on pahis eikä sitä saa käyttää. Eivät kai tienneet että onhan niitä muitakin samaan tehtävään kelpaavia käskyjä.
- esimerkiksi: BASH pitää kirjaa muuttujistaan ja antaa kirjanpitonsa käytettäväksi kaikkialla käskyllä: declare - se toimii myös funktioissa. Ja se on varmaankin jopa tehty siihen viittausten palauttamiseen - ja parametrien palauttamisen tarpeettomaksi tekemiseen.

3
Tämä postaus meni uusiksi:

Vasta tulkki tekee päätöksen siitä minkä roolin se muuttujalle milloinkin antaa: käsitetäänkö muuttuja niinkuin se olisi numero-arvo, tekstijono, jonkinsortin matriisi ... vai annetaanko sille merkitys käskynä, funktiokutsuna, matemaattisena kaavana, laskeeko se ja totettaako se totuusarvon, joukkotoiminteen, ascii-arvon, bitti-operaation, minkä hyvänsä. Myös matriisien jäsenet voivat toimia minähyvänsä näistä, myös assosiatiivisten matriisien jäsenet.

BASH on sekin käsky-pyramidi - jokainen käsky voidaan rakentaa hyväksikäyttämään kaikkea jo tehtyä - niin BASH:in omia käskyjä kuin tehtyjä funktioita - siinäpä työsarkaa tutkia kuinkahyvin sillä vaihtoehtoja on niin pajon ettei ole mahdollista kokeilla niistä pientä osaakaan. Lisäksi tässävaiheessa kannattaa tehdä mitä kummallisempia skriptejä joilla ei tällähetkellä tunnu olevan käyttöä - myöhemmin käyttöä todennäköisesti tulee. Käsitelläänpä joitain noista toiminnoista antamalla hommasta esimerkki:

1. Toimiminen käskynä, esimerkki1: todella merkittävästä ja isosta mutta väärin toimivasta skriptistä koetetaan usein etsiä vikapaikkaa vianetsintä-ohjemalla, debuggerilla. Kyseessä on siis homma jossa parempaa koetetaan korjata huonommalla - onhan debuggerien kanssa kiva leikkiä mutta eipä hommassa skriptaamisen kannalta paljon järkeä ole. Mutta on yksi helppo mutta silti tosihyvä debuggaus-menetelmä joka sopii niin pieniin kuin suuriinkin skripteihin: kirjoittaa skriptissä erittäin runsaasti välituloksia. Mutta et varmasti halua saada jokaisesta pikkuhommastakin paria sivua välitulosteita joten eikun skriptin valmistuttua poistamaan kaikki skriptin miljoona välitulostusta. Jonka jälkeen huomaat skriptiä vähänaikaa käytettyäsi että jokin on edelleen pielessä - joten eikun palauttamaan ne miljoona echoa muuttujineen.  Parin poisto-palautus kierroksen jälkeen oletkin kypsä. Tässä tulee apuun se että BASH:in muuttujat voivat toimia käskyinä: echon tilalle laitetaankin muuttuja jonka arvona on käsky echo tai käsky : joka ei tee mitään.
- siis: tulosta=echo  tai: tulosta=: . Koska : on sekin käsky tulkitaan perässätulevat tulostettaviksi tarkoitetut muuttujat parametreina ihan niinkuin echo:nkin kanssa.

Toimiminen käskynä, esimerkki2:
Koodia: [Valitse]
a='echo nyt kiristää pipoa'; $a   # tästä ei tule huomautusta niinkuin silloin tulisi jos a olisi tavallinen muuttuja - mutta ensiksi tässä tuleekin käsky.
a='eval set $b'; b='jostakin tekstistä tässäkin puhutaan'; $a; echo $3' '$4' '$1' '$2   
2. Toimiminen funktiokutsuna:
Koodia: [Valitse]
function koe () { echo täällä ollaan $1 ;}; a=koe; $a ' tälläkin kertaa' # siis tällaiseenkin käskyyn voi liittää parametrit ihan normaalisti.
3. Toimiminen matemaattisena kaavana:
Koodia: [Valitse]
function ratkaisija () { echo $1 | tr '[]' '()' | sed 's/x/'$2'/g' | bc -l ;};
a=x^2+x+1; ratkaisija $a 2.54   
- siis ratkaistaan yhtälö $a:n arvolla 2.54 - mutta kaavaksi voi kirjoittaa vaikka millaisen litanian sellaisia käskyjä jotka bc osaa ratkaista ja kirjoittaa arvoksi mitä lystää.
- kaavan suluiksi täytyy kirjoittaa hakasulut - esimerkiksi kun halut laskea jotain trigonometrista (luvut radiaaneissa): 
function ratkaisija () { echo $1 | tr '[]' '()' | sed 's/x/'$2'/g' | bc -l ;}; a=.2; ratkaisija s[$a]/c[$a]  # sin.2/cos.2  - taitaa olla tan.2 ?

- toisten käskyjen lomassa näitä käskyjä käytetään esimerkiksi näin: tarkistellaan matematiikkamoottoriin lähetettävää lausetta:
Koodia: [Valitse]
$(($apu$merkki(( ${desimaaliosa:$2:1} >= 5 )) ))
-> BASH kokoaa ensin sellaisen tekstijonon kuin käsky määrää. Lähetettäessä tekstijono matematiikka-moottoriin sen osista jokainen määritellään sentyppisesti kuin hyvä tulee: siis jokainen osa voi olla tarpeen mukaan joko: tekstijono, numero, operaattori, laskutoimitus, funktiokutsu tai looginen arvo 0 tai 1 -> kaikki mitä sinne matematikka-moottoriin lähetetäänkin tuntuu toimivan.

- mutta näitäkään toimintoja ei tiedetä hyödyntää sillä niistä ei opeteta missään. Epäoikeudenmukaisesti sanottuna: miksi opettaa kun on helpompaa sanoa ettei BASH osaa.

4
Neliöjuuri kannattaa BASH:issa laskea luvun tieteelllisestä esitys-muodosta. Tieteelliseen esitysmuotoon ei kannata siirtyä käskyllä printf vaan tehdä funktio joka tekee saman muunnoksen täsmälleen samallatavoin ja toimii erittäin nopeasti - sillä myös käsky printf on suunniteltu hukkaamaan aikaa - printf on kyllä erittäin monipuolinen käsky sillä sitä voi käyttää myös säilyketölkkien avaamiseen.   
 
Koodia: [Valitse]

function sqrt () { apu=${1##+(0)}; [[ $apu ]] || { echo 0; return ;} # lausetta tarvitsee vain kun lasketaan:  sqrt 0  . Tai: sqrt 00000....
function to_sci () { [[ $1 =~ e ]] && echo $1 || { apu=$1; [[ ${apu:0:1} = - ]]  && merkki=- || merkki=''; apu=${apu//[-+]/}; apu=${apu##+(0)}; kokonaisosa=${apu%%.*};[[ ${apu//[^.]/} ]] && desimaaliosa=${apu##*.} || desimaaliosa=0; [[ $kokonaisosa ]] && { expo=${#kokonaisosa}; echo $merkki${kokonaisosa:0:1}.${kokonaisosa:1}$desimaaliosa'e'$(($expo-1)) ;} || { apu=${desimaaliosa%%[1-9]*}; ekspo=$((${#apu}+1)); desimaaliosa=${desimaaliosa:$(($ekspo-1)):1}.${desimaaliosa:$(($ekspo))}; echo $merkki$desimaaliosa'0e'-$ekspo ;} ;} ;}

apu=$(to_sci $1); mant=${apu%%e*};apu=${apu##*e}; apu=${apu//+0/}; apu=${apu//-0/-}; (( $apu & 1 )) && kerroin=10 || kerroin=1; expo=$(($apu/2));   
in=${mant//./}"000000000000000000"; in=${in:0:17}
sqrt=2147483648  # 2^31 
delta=1073741824 # 2^30 # tämä tulee voida jakaa jatkuvasti kahdella siten että jako menee aina tasan 
for ((i=0;i<30;i++)); do
   x=$(($sqrt*$sqrt/$kerroin))
   (( $x>=$in )) && sqrt=$(($sqrt-$delta)) || sqrt=$(($sqrt+$delta))
   delta=$(($delta/2)) #; (( $delta )) || delta=1  # echo $((1/2)) lasketaan nollaksi - oikein pyöristettynä se on 1
done
#echo -n 'bc:stä ';bc -l <<< "sqrt($juurrettava)" # bc ei puutu laskuihin mitenkään vaan se laskee varmasti oikean tuloksen johon verrata. Mutta kun lauseen kommentoi niin silloin ei varmasti puutu.
apu=00000000000000000000000000000000000000000000000000$sqrt'000000000000000000000000000000000000000000000';apu=${apu:0:$((51+$expo))}.${apu:$((51+$expo))}
luku=${apu##+(0)}; [[ ${luku//[^.]/} ]] && luku=${luku%%+(0)}; echo ${luku%.}  ;}
   
 # esimerkkilaskuja: 
juurrettava=27.456789;time sqrt $juurrettava

juurrettava=2.7456789e-99;time sqrt $juurrettava
juurrettava=2.7456789e-98;time sqrt $juurrettava

juurrettava=2.7456789e+99;time sqrt $juurrettava
juurrettava=2.7456789e+98;time sqrt $juurrettava

juurrettava=0000000000000;time sqrt $juurrettava


***

Täytyy myöntää että nykytilanne turhauttaa, sillä kyse ei suinkaan ole siitä että nämä skriptini kelpaisivat käytettäväksi. Vaan kyse on siitä että ne kertovat että me uskomme kaiken mitä meille kerrotaan silloinkin kun se kerrottu on mahdotonta.

Esimerkiksi äskeinen sqrt samoinkuin aikaisemmin esitetty 36 numeroinen liukuvanpilkun kertolasku kerro18 toimivat BASH-skripteiksi salaman-nopeasti ja moitteettomasti jo kaksi vuotta sitten - ja mikäli ne olisi kasattu jo kolmekymmentä vuotta sitten kun BASH:ia alettiin romuttamaan olisivat ne toimineet jo silloin - sillä niissä ole mitään uutta - päinvastoin uudemmat käskyt on ilmeisesti tahallaan tehty sellaisiksi että nuo paremmat menetelmät alkavat nikotella jos mukaan otetaan jotain uudempaa. Mutta silti virallinen opetus on vieläkin etteivät tämmöiset BASH:issa edes toimi.

Nyt alkaa hiukan kajastaa syy miksi BASH:ista levitetään suoranaisia valheita: sen aikaansaa halu osoittaa että BASH on täysin kelvoton verrattuna muihin skriptikieliin niinkuin esimerkiksi: sed, awk, bc, Perl ja Python - ettei vaan pääsisi syntymään sellaista tilannetta että BASH kilpailisi niiden kanssa. Nimittäin silloin aikoinaan BASH ei tosiaankaan ollut kelvoton muihin verrattuna - nykyään BASH on kelvoton kolmenkymmenen vuoden heitteille jättämisen seurauksena - mutta onko se kelvottomuuskin paljolti näennäistä?

Myös BASH:in tarina on näemmä pelkkää historian kertausta - samoja tarinoita kerrotaan yhä uudelleen sillä uusia ei osata tehdä: tässäkin virtuoosit väittävät etteivät he ole tehneet mitään mutta kuitenkin pesevät kätensä kuin Pontius Pilatus.

5
Edellisessä tehtävässä printf:n tehtävänä on muuntaa normaalilla tavalla esitetty luku tieteelliseen esitys muotoon: x.xxxxx e yy. 'Nopeilla käskyillä' tehtynä muunnos tapahtuu noin kuusikertaa nopeammin. Ei se koodin laadusta johdu vaan ohjelmien koosta: printf on 50K järkäle ja to_sci on vajaa kilo:
[
Koodia: [Valitse]
function to_sci () { apu=$1; [[ ${apu:0:1} = - ]]  && merkki=- || merkki=''; apu=${apu//[-+]/}; apu=${apu##+(0)}; kokonaisosa=${apu%%.*};[[ ${apu//[^.]/} ]] && desimaaliosa=${apu##*.} || desimaaliosa=0; [[ $kokonaisosa ]] && { expo=${#kokonaisosa}; echo $merkki${kokonaisosa:0:1}.${kokonaisosa:1}$desimaaliosa'e'$(($expo-1)) ;} || { apu=${desimaaliosa%%[1-9]*}; ekspo=$((${#apu}+1)); desimaaliosa=${desimaaliosa:$(($ekspo-1)):1}.${desimaaliosa:$(($ekspo))}; echo $merkki$desimaaliosa'0e'-$ekspo ;} ;}
# mutta ei ääretöntä kovin nopeasti saa testattua:tämä vaatii uskomattoman monia tarkituksia - tämä on vain alkua:
to_sci 1
to_sci 10
to_sci 010
to_sci 1000000
to_sci +1000000
to_sci -1000000
to_sci .1
to_sci .01
to_sci 0.01
to_sci -.01
to_sci +.01
to_sci -0.01
to_sci -0.01
to_sci 123456789012345678901234567890123456789012345678901234567890   # nimenomaan eksponentin tulee olla oikein
to_sci .00000000000000000000000000000000000000000000000001                      # nimenomaan eksponentin tulee olla oikein
to_sci .00000000000000000000000000000000000000000000000001234567890
to_sci -123.0124
to_sci -123.0000000000123

- näillä itsetehdyillä ohjelmilla on yksi voittamaton piirre valmisohjelmiin verrattuna: jos itsetehty toimii väärin niin sitten se korjataan. Mutta valmisohjelmalle et voi mitään.
- näillä itsetehdyillä on rajoitetussa määrin jopa toivottavaakin että joskus toimii väärin: tarkoituksenahan on aivojumppa. Ei merkitse kovin paljoa sekään että onnistuuko korjaamaan toiminnan oikeelliseksi - sekin riittää että yrittää.
- on inhottavaa ja pelottavaa tehdä uudentyyppisiä kokeita - sillä aivan varmaa on että jotakin on jäänyt huomaamatta ja varmasti joskus kompastuu - ja etukäteen ei voi tietää saako vikaa koskaan korjattua. Mutta todella tuntee elävänsä.

6
 Olipa kerran suurvisiiri joka halusi kalifiksi kalifin paikalle - siis tässätapauksessa BASH:in paikalle. Mutta BASH oli aivan liian vahva jotta sitä olisi kannattanut haastaa. Siispä BASH:ia täytyi huonontaa paljon. Valhe on viisainta perustaa totuuteen joten kuka nämä tekikin puhui aina täysin totta mutta asetti sanansa niin taitavasti että käyttäjät älyttivät itsensä:
1. luulemaan etteivät esimerkiksi desimaalilaskut BASH:issa onnistu eivätkä siten edes yrittäneet tehdä niitä.
2. luulemaan että BASH kuuluu niihin mölleihin ohjelmiin joiden täytyy parametreja palauttaa - siis on ihan totta ettei BASH osaa parametreja palauttaa muttei palauttamisessa mieltä olekaaan.
3. hän myös häivytti desimaalilaskentaan pystyvät käskyt historian hämäriin uudella käskykannalla joka on desimaalilaskuissa tuhansia kertoja hitaampaa. Käytännössä tämä johtaisi siihen että vaatimatonkin desimaalilasku kestäisi uudella käskykannalla 10 minuuttia eikä kukaan viitsi niin kauaa yhtä pientä laskua tehdä.

Tässä on yksi desimaalilaskujen toteutus jonka sain nyt moitteettomaan kuntoon - sanotte varmaan ettei tässä mitään desimaaleja ole - johon vastaan että eihän niitä muulloinkaan ole, mielikuvahan se desimaali on (tai tieteelisemmin selitettynä: desimaali on asteikko jossa luku esitetään. Ja  asteikko määritellään numero-laskuista hieman erillään - tässä tuo printf on siinä merkityksellisin tekijä.) :
Koodia: [Valitse]
function sqrt () {
apu=$(LC_NUMERIC=C printf "%.17e\n" $1); mant=${apu%%e*};apu=${apu##*e}; apu=${apu//+0/}; apu=${apu//-0/-}; (( $apu & 1 )) && kerroin=10 || kerroin=1; expo=$(($apu/2));   
in=${mant//./}"000000000000000000"; in=${in:0:17}
sqrt=2147483648  # 2^31 
delta=1073741824 # 2^30 # tämä tulee voida jakaa jatkuvasti kahdella siten että jako menee aina tasan 
for ((i=0;i<32;i++)); do
   x=$(($sqrt*$sqrt/$kerroin))
   (( $x>=$in )) && sqrt=$(($sqrt-$delta)) || sqrt=$(($sqrt+$delta))
   delta=$(($delta/2)); (( $delta )) || delta=1  # echo $((1/2)) lasketaan nollaksi - oikein pyöristettynä se on 1
done
#echo -n 'bc:stä ';bc -l <<< "sqrt($juurrettava)" # bc ei puutu laskuihin mitenkään vaan se laskee varmasti oikean tuloksen johon verrata. Mutta kun lauseen kommentoi niin silloin ei varmasti puutu.
apu=00000000000000000000000000000000000000000000000000$sqrt'000000000000000000000000000000000000000000000';apu=${apu:0:$((51+$expo))}.${apu:$((51+$expo))}
luku=${apu##+(0)}; [[ ${luku//[^.]/} ]] && luku=${luku%%+(0)}; echo ${luku%.}  ;}


juurrettava=9;time sqrt $juurrettava
tai: juurrettava=73.456789e-3; time sqrt $juurrettava

- neliöjuuri luvuista: 4,9,16,25...1152921504606846976 esitetään aina kokonaislukuna sillä laskettaessa niiden desimaaleiksi tulee 0.
- eihän tämmöisellä skriptillä enää nykyisin tee mitään. Mutta tarkoitus onkin varmistautua taas vähän lisää siitä että puhuu asiaa väitteessä että on sössitty tahallisesti.

HUOMAUTUS: ei ääretöntä lukualuetta ole nähtävästi mahdollista hoitaa moitteettomasti: esimerkiksi lasku luvuilla joissa eksponentti oli -8 tai -9 päätyivät virheeseen - sitä pienemmät ja suuremmat luvut toimvat. Siitä nämä 'nopeat käskyt' ovat mukavia että niitä saa tulla lisää monta ennenkuin se näkyy missään joten uusittu koodi on yhtä nopea kuin vanhakin.

7
BASH oli kauan sitten kunkku - se jopa koettiin nopeaksi vaikka hidashan se on aina ollut eikä sen kykyjäkään ole koskaan paljoa hyödynnetty tietokoneen hoitamisen lisäksi - mutta eivät ne vaatimuksetkaan aikoinaan kovin kaksisia olleet. Mutta sitten virtuoosit siirsivät BASH:in satuun nimeltään: kuninkaalla ei ole vaatteita. Saman-nimisessä oikeassa sadussa tarvitaan pikkupoika sanomaan että alastihan kuningas on eikä komeasti vaatetettu niinkuin virtuoosit väittävät - ja senjälkeen kaikki muutkin uskalsivat myöntää etteivät he mitään vaatteita näe. Mutta BASH on päinvastainen tapaus: siinä virtuoosit väittävät ettei BASH:illa ole vaatteita. On melkein mahdotonta että tavis väittäisi vastaan ja sanoisi että BASH:in vaatteet ovat kyllä varsin resuiset mutta sittenkin vaatteita on - sillä häntä ei joko uskottaisi tai vaiettaisiin väitteet kuoliaaksi joten väittäjältä menisi maine - mutta minun maineeni meni jo kauan sitten joten voin väittää mitävaan.

Kyllä virtuoosit puheistani huolimatta ovat mielestäni hatun-noston arvoista ja pätevää porukkaa. Sitä en tosin käsitä miksi nimenomaan BASH on heidän hampaissaan.

On totuttu mollaamaan BASH:ia tyylliin: ei BASH osaa. Ei tietenkään osaa - mutta se on näennäistä sillä kirjastoissahan ne paremmat hommat luuraa ja virtuoosithan ovat asettaneet 'kirjastokiellon'. Mutta kyllä BASH sittenkin osaa - skriptin yhteydessä olevissa funktioissa. Onpa hankalaa mutta niin virtuoosit tahtovat.

Esimerkiksi ensimmäisen asteen funktiot - on omituista ettei BASH:in yhteydessä tästäkään edistyneemmästä ominaisuudesta kerrota mitään eikä niistä oikeastaan puhutakaan missään mitään - paitsi sana siellä ja toinen täällä sillä virtuoositkaan eivät malta olla ihan hiljaa edistyneemmästä BASH:ista. Tämäkin yhteenveto on koottu ziljoonilla verkkosivuilla olleista tiedoista.

'Ensimmäisen asteen funktiot' toimivat hyvin BASH:issakin. Mutta nimitys 'ensimmäisen asteen funktiot' on hämäävä ilmaisu sillä kyseessä on tulkin kyky tulkita muuttujalta näyttävä funktio-kutsuna mikäli siinä olevan tekstijonon ensimmäinen sana on sama kuin jonkin funktion nimi - eteenpäin viittaukset sallitaan - ja pitää muuttujassa mahdollisesti olevia loppuja arvoja tuon funktion parametreina.

Tuo parametri hommeli on muuten ovela juttu: luku on aina arvoparametri ja niin on tekstikin yleensä - mutta tekstijono tulkitaan nimiparametriksi mikäli saman-niminen muuttuja löytyy skriptistä jostain paikasta, vaikka myöhemminkin määriteltynä - suokaa anteeksi virtuoosit, eihän tämmöistä saisi kertoa - esimerkiksi tässätapauksessa muuttujasta jonka nimi on:numero puhutaan vasta funktiokutsun jälkeen joten tulkin täytyy sittenkin käydä skripti läpi ainakin kahdesti. Esimerkki:
Koodia: [Valitse]
function koe () { $1 numero; echo $numero ;}       # funktion nimeltä:koe parametri $1 on tekstijono:joo joka tulkitaan funktiokutsuksi ja muuttuja nimeltään numero sen nimi-parametriksi.
function joo () { readarray $1 < <(echo 12345) ;}  # tässä funktiossa $1 on nimiparametri nimeltään: numero - ja sille annetaan arvo 12345. Kun on palattu funktioon: koe ja jatketaan siinä
                                                   # olevan skriptin suoritusta välittömästi kutsu-paikan perästä ja tulostetaan muuttujan nimeltä:numero arvo käskyllä: echo $numero.
# annapa käsky:
koe joo 
# jolloin tulostuu: 12345
- siis vasta kääntäjä tekee päätöksen sitä minkä merkityksen se muuttujalle milloinkin antaa - tämä on siis aivan samanlainen tapaus kuin se jossa matematiikkamoottori tulkitsee sille annetun tekstin niinkuin hyväksi havaitsee.
- kun selittää kuinka joku menetelmä toimii kannattaa muuten selittää mahdollisimman paljon - silloin selittää myös itselleen joten tajuaa paremmin onko kaikki oikein. Ja vaikka selityksestä on useimmille lukijoilla pääosa itsestään selvää niin varmasti on joku sellainenkin lukija joka tarvitsee selitystä myös niissä itsestään selvissä kohdissa - ja sieltä pohjilta ne tulevat virtuoositkin kasvavat.

8
Funktion onkoekasuurempi lyhyempi versio osaa 'laskea' 32 numeron tarkkuudella 0.5 millisekunnissa. Silti lasku kuulunee skriptilajiin 'party trick' sillä eihän tämmöistä uskalla nykyään käyttää - mutta silloin kolmekymmentä vuotta sitten tämä olisi ollut kova juttu. Ja tiedähäntä mitä tästä saisi jalostettua - aikanaan se olisi kovastikin kannattanut mutta ei taida kannattaa enää tänäpäivänä. Tämä taas sarjassamme 'kummallisia sattumuksia'.
Koodia: [Valitse]
function onkoekasuurempi () { luku1=${1//[^-.0-9]/}; luku1=${luku1%.}; luku2=${2//[^-.0-9]/}; luku2=${luku2%.}; [[ ${luku1//[^-]/} ]] && m1=- || m1=''; [[ ${luku2//[^-]/} ]] && m2=- || m2=''; (( 10#0${luku1//.*/} == 10#0${luku2//.*/} )) && { desimaalit1=${luku1//*./}000000000000000000; desimaalit2=${luku2//*./}000000000000000000; (( $m1${desimaalit1:0:18} <= $m2${desimaalit2:0:18} )) && echo 0 || echo 1 ;} || { (( 10#0${luku1//.*/} <= 10#0${luku2//.*/} )) && echo 0 || echo 1 ;} ;} 
onkoekasuurempi 1234567890123456*1234567890123456 1524157875323881726870921383936 -> tulostaa 0 niinkuin pitäisikin
onkoekasuurempi 1234567890123456*1234567890123456 1524157875323881726870921383937 -> tulostaa 1 niinkuin pitäisikin

- 1234567890123456*1234567890123456 = 1524157875323881726870921383936
- ajatelkaa BASH:in monipuolisuutta - lukujen vertaamiseen tarkoitettu funktio on samalla myös osittain pätevä laskin - tekemättä kertakaikkiaan mitään.
- kyllä muutkin luvut toimivat samoin joten saisihan tästä tehtyä monenmoista.

9
Nyt alkoi selvitä miksi BASH on siinä tilassa kuin se on kun luin Ruotsin liikennekaoksesta, Norjan suojelupoliisin varoituksista jne jne. Asiat tiedostetaan ja konferensseja pidetään - mutta itse ei varmasti tehdä mitään eikä anneta toistenkaan auttaa vaan kielletään kaikkia tekemästä mitään sillä siitähän seuraisi että saattaisi joutua johtamaan koko hommaa joten viini, laulu ja naiset täytyisi unohtaa. Vastuuta pakoillaan vaikka ulkopuoliset selväsanaisesti sanovat että katastrofi on jo muodostunut.

Samasta syystä väitetään esimerkiksi ettei BASH tunne desimaalilukuja? Tämän aasin-sillan kautta pääsen selvittämään desimaalilukujen vertaamista taas kertaalleen mutta tälläkertaa  matemtiikkamoottorin avulla - se '$((1+2))' - sillä mikäli joskus tekisi BASH-skriptin matematiikkaa varten tulisi sen vertailu-funktion olla tosinopea - bc:t ja muut voit unohtaa sillä vertailun täytyy olla tehty jo ennenkuin ne edes aloittavat. Ja 'nopeilla käskyillä' tehdyt skriptit ovatkin tosinopeita vaikka niissä olisi monia tai vielä useampia käskyjä.

Lukujen vertaaminen kannattaa tehdä matematiikkamoottorilla sillä se on paljon nopeampaa kuin tekstijono-vertailu - niin nopeaa ettei sitä saa mitattuakaan - ja myös desimaaliluvut täytyy hyväksyä mutta koska matematiikkamoottori ei hyväksy desimaaleja täytyy lukujen kokonais- ja desimaaliosat verrataan erikseen. Silloin toiminta on seuraavanlaista:

1. Kaikki muu kuin numerot, miinus-merkki ja desimaalipiste poistetaan - tai mikäli desimaalipiste on viimeisenä niin sekin poistetaan. Kokonaislukujen miinus-etumerkki laitetaan muistiin mutta etumerkkiä ei poisteta. Desimaaliosien loppuun lisätään nollia niin monta että ne ovat 18 numeroisia sillä desimaaliosien vertaaminen ei mene oikein ellei molemmissa desimaaaliosissa ole numeroita yhtämonta.
2. Mikäli kokonaisluvut ovat yhtäsuuret tulee lopputulos yksinomaan desimaalien vertaamisesta. Desimaalien vertaamisessa täytyy huomioida kokonais-osien etumerkkit.
3. Mutta jos kokonaisluvut eivät olleetkaan yhtäsuuria niin vertailutulos tulee yksinomaan kokonaislukujen vertaamisesta. Etumerkit huomioidaan automaattisesti.

Tämmöisistä täytyy ehdottomasti olla funktio kirjastossa sillä hermothan tämmöisiä väsätessä menee, aikaa haaskaantuu ziljoonaan kokeeseen ja sittenkin sielua jää kaivertamaan tieto siitä että ihan varmasti jotakin on jäänyt huomioimatta tai että on luonut sellaisen skripti-hirviön ettei pysty enää hallitsemaan sitä ... :
Koodia: [Valitse]

function onkoekasuurempi () { luku1=${1//[^-.0-9]/}; luku1=${luku1%.}; luku2=${2//[^-.0-9]/}; luku2=${luku2%.}; [[ ${luku1//[^-]/} ]] && m1=- || m1=''; [[ ${luku2//[^-]/} ]] && m2=- || m2=''; (( 10#0${luku1//.*/} == 10#0${luku2//.*/} )) && { desimaalit1=${luku1//*./}000000000000000000; desimaalit2=${luku2//*./}000000000000000000; (( $m1${desimaalit1:0:18} <= $m2${desimaalit2:0:18} )) && echo 0 || echo 1 ;} || { (( 10#0${luku1//.*/} <= 10#0${luku2//.*/} )) && echo 0 || echo 1 ;} ;}

onkoekasuurempi 12345679012345678.12345679012345678 12345679012345678.12345679012345678
onkoekasuurempi .1 0.1
onkoekasuurempi 1 .1
onkoekasuurempi 1 1
onkoekasuurempi +1 1
onkoekasuurempi -1 -1
onkoekasuurempi -1 1
onkoekasuurempi 1 -1
onkoekasuurempi 1.9 1.89
onkoekasuurempi 1.000000000000000001 1
onkoekasuurempi 2. 1.   # tai: onkoekasuurempi 2$ 1$ tai: onkoekasuurempi 2km/t 1km/t ...
- sekä desimaaliosat että kokonaisosa saavat olla 0 - 18 numeroisia, desimaalipilkku saa olla tai sitten ei ja verrattavat luvut voivat olla pelkkkiä numeroita tai niissä saa olla mukana mitähyvänsä lukuja tarkemmin määrittelevää tekstiä.
- tuleeko mieleen presedenssi kun antaa käskyn: luku=${luku//[^-.0-9]/} -> ei toimi jos kirjoittaa: luku=${luku//[^.-0-9]/}. Että yksinkertainen kieli?
- muuten esimerkiksi: onkoekasuurempi 6-2 4 -> 0 . Kokonaislukujen miinuslasku siis toimii mutta taitaa olla viisainta jättää muu matikka tässä yhteydessä pois.

10
Kun pakolliset rinkulat on nyt tehty niin pistetäänpä vauhtia masiinaan (siis toiminta oli: etsitään tekstistä jokainen haettava ja tulostetaan yksinomaan niiden sanojen loppu jossa haettava on
- siis tulostetaan välilyöntiin tai rivinloppun asti):
Koodia: [Valitse]
function takaosa () { for word in ${@:1}; do [[ "$word" =~ $1 ]] && echo ${word#*$1}; done ;}
# kutsut ovat kirjoitusasultaan: sana:takaosa haettava_teksti teksti_josta_haetaan
# -   rivinsiirrot sallitaan. Silloin teksti täytyy laittaa heittomerkkien väliin:
time takaosa ma "ma1 kkk kkkma2 ma3 ma4jjjjj gggggma5
ma6 ma7 hhhhma9ppppp ma10 xyz ma11 ggggma12"
- tai mikäli kyse on tiedostoon kijoitetusta tekstistä:
Koodia: [Valitse]
time takaosa B $( cat /boot/grub/grub.cfg)
- 'nopeisiin käskyihin' perustuvat skriptit ovat pienissä etsintätehtävissä nopeampia kuin sed-awk-grep-regex toteutukset  mutta mutta vähänkin isommissa etsintätehtävissä ne ovat hitaampia ja isoilla tiedostoilla jopa yli kymmenenkertaa hitaampia - mutta 'nopeista käskyistä' tehty skripti tarjoaa sellaista mikä muille olisi mahdotonta tai ainakin hyvin vaikeaa - ja 'nopeista käskyistä' tehtyä skriptiä voi tästäkin räätälöidä edelleen mihin tarkoitukseen tahansa. 

- myös grep+regex on varsin pätevä tallaisiin toimiin - mutta muistihirviö-skriptaajienkin täytyy opiskella sitä tosikauan ennkuin alkaa sujumaan. Eikä noiden muidenkaan skriptikielten soveltaminen yksinkertaista ole.

11
Tällä kertaa tarkoituksena on muuttaa edellä esitetty rekursiivinen versio tavalliseksi - siis tavallaan tehdä uudestaan - ja usein kun skriptn tekee täysin uudelleen niin se samalla yleensä yksinkertaistuu ja nopeutuu - ellei mähli:
Koodia: [Valitse]
function takaosa () { apu="$(echo ${1//\\n/ })"; while [[ "$apu" =~ $2 ]]; do apu="${apu#*$2}"; echo ${apu%% *}; done ;}
takaosa "$( cat /boot/grub/grub.cfg)" B
tulostuu:
EGIN
e
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN

- löytyneistä ensimmäinen on tekstin alustapäin ja viimeinen lopustapäin.
- EGINIT tulevat sanoista BEGIN. Yksinäinen e tulee siitä että tiedotossa yksi lause alkaa: Be
- haku voidaan kirjoittaa myös: 
Koodia: [Valitse]
takaosa "$(readarray -t a < /boot/grub/grub.cfg; echo "${a[@]}")" B   
- hakuaika putoaa kolmasosaan kun hakutermiksi kirjoitetaan pieni b - vaikka löytöjä tulee neljäkertaa enemmän - olen äimänkäkenä siitä mikä tuommoisen voisi aiheuttaa. A/a on vähän toistapäin.

12
- tiedostosta lukeminen tapahtuu näin:
Koodia: [Valitse]
   takaosa "$( < /boot/grub/grub.cfg)" BE # tulostuu: GIN . Tai kun on syytä olettaa että etsittävä löytyy 100:lta ensimmäiseltä riviltä jättikokoista tiedostoa:
   takaosa "$( head -100 ~/tmp)" aa
- eivät nämä BASH-toteutukset vastaa nopeudeltaan läheskään sitä mihin esimerkiksi käsky:grep kykenee eikä näistä luultavasti nopeita saakaan. Eikä ilman kirjastoja näistä saa helppoja käyttääkään. Mutta jos kirjastoja käyttäisi niin grep jäisi monipuolisuudessa toiseksi sillä näistä voi räätälöidä hieman erilaisia versioita vaikka kuinkapaljon - aikaisemmin tuntemattomiinkin tarpeisiin. Tuntuu yhä enemmän siltä että virtuoosit ovat keksineet BASH:ille vaikeuksia ettei se kilpailisi sed:in, awk:in, grep:in ja muiden semmoisten kanssa.       

***

Tai jos funktion halutaan tulostavan kaikki löydetyt niin funktio voidaan tehdä rekursiiviseksi. Näillä 'nopeilla käskyillä' rekursio on nopea joten nopeus-tappio on pieni. Tässä tulostus-suunta on viimeisestä ensimmäiseen mutta pienellä koodimuunnoksella sen saisi muutettua ensimmisestä vimeiseen. Esimerkiksi:
 
Koodia: [Valitse]


function takaosa () { apu="${1##*$2}"; apu=${apu//\"}; echo ${apu%% *}; [[ "${1%$2*}" =~ $2 ]] || return; takaosa \""${1%$2*}"\" "$2"  ;}

takaosa "ma1ma2makolme ma4 ma5
ma6

 ma7
ma8 ma9
ma10" ma

Tulostuu:
10
9
8
7
6
5
4
kolme
2
1

***

Tiedostosta etsittäesssä vain kutsu kirjoitettaisiin eritavalla:
Koodia: [Valitse]
function takaosa () { apu="${1##*$2}"; apu=${apu//\"}; echo ${apu%% *}; [[ "${1%$2*}" =~ $2 ]] || return; takaosa \""${1%$2*}"\" "$2"  ;}
takaosa "$( < /boot/grub/grub.cfg)" B

tulostuu:
 
EGIN
e
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN


- etsintä siis huomioi kirjainkoon joten sillä siellä on keran Be
- koetapa:  takaosa "$( < /boot/grub/grub.cfg)" b

13
Oletpa oikeassa, sotkeuduin taas lahkeisiini. Taisi ylirasitus iskeä ja poistun lepäämään ainakin joksikin aikaa. Silti vielä: BASH:hissa on grep:in tai regex:in kaltaista nopeaa hakua, mutta kuitenkin ihan erilaista:
Koodia: [Valitse]

function etuosa () { apu="${1%%$2*}"; echo ${apu##* } ;}        # tulostaa ensimmäisen löydetyn edessäolevan
# tai: function etuosa () { apu="${1%$2*}"; echo ${apu##* } ;}  # tulostaa viimeisen löydetyn edessäolevan
# tai: function etuosa () { apu="${1%$2*}"; echo ${apu#* } ;}   # tulostaa koko välin ensimmäisestä viimeiseen löydettyyn
                   
etuosa "unten siivin luoksesi hiivin
        suutelen silmäsi uneen
                         
        vartiopaikalla suorana seisten
        kirjoitan nimesi lumeen" kal 
     
- siis 'ensimmäisen löydetyn edessäolevan' tapauksessa: kal on se mitä etsitään - tulostuu: vartiopai
- pitää määrätä hakutermi oikein tai saa tyhjää käskystä. Siis määritä haku näin:
  etuosa "keke roosberg syöksyi mutkaan nopeudella 235 km/t" " km/t" # näin löytyy tuo 235 - huomaa välilyönti hakutermin alussa.

--- tai:
Koodia: [Valitse]

function takaosa () { apu="${1##*$2}"; echo ${apu%% *} ;}        # tulostaa ensimmäisen löydetyn perässäolevan
# tai: function takaosa () { apu="${1#*$2}"; echo ${apu%% *} ;}  # tulostaa viimeisen löydetyn perässäolevan
# tai: function takaosa () { apu="${1#*$2}"; echo ${apu% *} ;}   # tulostaa koko välin ensimmäisestä viimeiseen löydettyyn
                                                   
takaosa "kun mä kuolen sadetakkini sä saat
         sillä olen varma että
         pilv1enpääl ei sada vettä
         huh hah hei ja rommia pullo" "ma "
- tulostuu:että . Ja "a " tuostaa:pullo . Ja ma*sa tulostaa:da .  Ja: [0-9][iest] tulostaa:npääl. Kaikki niinkuin pitäisikin.
- huomioi että * ylittää sekä välilyönnit että rivinsiirrotkin.

14
Ihan alkuunsa BASH:ia syytettiin eniten hitaudesta - ja hitaus olikin kiistatonta johtuen hitaista käskyistä - tulkattavasta käskystä tulee hidas jos siihen lisätään runsaasti ominaisuuksia jotka täytyy tulkata tarvitaan niitä tai ei - ja kussakin käytössä tarvitaan vain yhtä ominaisuutta ja muut ovat turhaa painolastia. Koska 'nopeat käskyt' osaavat tehdä vain yhtä asiaa ovat ne nopeita - ja näyttää yhä enemmän siltä että nopeus saattaakin usein olla paljon-paljon parempi kuin on luultu.

Seuraavaksi alettiin mollata BASH:ia kyvyttömäksi - mutta 'nopeilla käskyillä' tehdyt skriptit ovat kyvykkäitä ja helpommin räätälöitävissäkin - joten ne toimivat paremmin ja niinkuin niinkuin etukäteen olettaisi - mutta nykyisistä käskyistä kootut skriptit tekevät yleensä sitä mutta toisinaan tätä - sillä ne ovat loogisia pommeja tarkoituksella tai tahallaan.

Skriptit olisi viisainta kirjoittaa funktiomuotoon - silloin voisi kutsua noita pitkiä skriptejä yhdellä sanalla. Mutta tämän estämiseksi annettiin 'kirjastokieto'?

Kirjastokieltoon voi suhtautua:
- ei välitä
- kirjastot jätetään tekemättä mutta kyllä funktioita saa tehdä. Eikä niitä funktioita tarvitse kirjoittaa vaan kopioida koko roska kerralla - tosin skripteistä tulee niin tehden nopeasti kammottavan kokoisia. Mikä on erittäin vahingollista aloitettaessa ohjelmointi sillä ihminen tajuaa nopeiten sellaisen joka voidaan esittää yhdellä sivulla.

Ainoa järkeväntuntuinen selitys 'kirjastokiellolle' on se että kirjastoissa on jotakin joka on tietoturvariski. Mikä pitää varmasti paikkansa sillä tietokone on tietoturvariski vaikka sen maalaisi vihreäksi ja heittäisi mereen. Selitys semmoisenaan on siis yhtätyhjän kanssa.

***

Luinpa kuinka jättikokoisen tiedoston viimeisen lauseen etsimisessä hehkutettiin komentoa: 'echo tiedosto | tail -1' - että se on melkein voitamaton - awk ja sed mukaanlukien. Olihan se ihan selvä haaste joten tein satunnaisesta tekstistä giga-luokan tiedoston nimeltään: ~/temp - ja sitten skriptin sen viimeisen rivin tulostamiseksi.
- pienen koetiedoston voi tehdä minuutissa käskyllä:
Koodia: [Valitse]
rm ~/temp;touch ~/temp; for n in {1..10000}; do echo $n'     '$(cat /dev/urandom | base64 | head -c 100) >> ~/temp; done

Toimintanopeuksia tosi-suurella tiedostolla:
Koodia: [Valitse]

cat ~/temp | tail -1                                                                                           #  kesti: yli minuutin
truncate -s-1 ~/temp; echo -n "¤" >> ~/temp; a=$(timeout .001 tac ~/temp); echo ${a%%¤*} ; truncate -s-1 ~/temp #  kesti 10 ms


Mutta täytyy myöntää ettei skriptin toiminta ole moitteetonta sillä jokainen käyttökerta lisää viimeisen rivin loppun jotakin vaikka näennäisesti kaikki lisätty poistetaan eikä editorissakaan näy mitään - ilmeisesti olisi toinen viikkojen pituinen etsintä löytää käsky jolla se lisätty poistetaan.

***

Olen aina inhonnut sitä kun jostain asiasta väitetään ettei BASH osaa sitä - sillä en ole löytänyt yhtään sellaista ongelmaa johon ei löydy aikanaan ratkaisua - ihan toinen asia on että ratkaisua joutuu useinkin etsimään kuukausia - ratkaiseminen on niinkuin palapeli johon löytyy palasia kauan - ja vaikka asiaa ei tietoisesti edes ajattele niin palapeli lymyää jossain aivonperukoissa - ja sitten omia aikojaan ratkaisu selviää kuin itsestään. Tosin siitä löytämisestä ei ole mitään varsinaista hyötyä sillä BASH on päästetty niin pahaan kuntoon ettei sitä korjaa koskaan enää mikään määrä virtuooseja - mutta saahan onnistumisesta sentään paljon mielihyvää.

Mutta noita palapelin osia ei kukaan pysty kokoamaan pelkästään omista tiedoistaan sillä BASH on niin laaja ettei edes kaikkia sen käskyjäkään kukaan voi hallita täysin: esimerkiksi tuon äskeisen käskyryhmän palasia kokosin netistä vuosia sillä siinä on kolme 'ratkaistavaksi mahdotonta' ongelmaa - ja ilmeisesti siis neljäs pitäisi vielä löytää. Muuten useimmat löytyneet palaset olivat jopa yli parikymmentä vuotta vanhoja - ei oikeastaan ihme sillä silloin käyttäjät alkoivat paeta BASH:ista.

15
Yritän jatkuvasti saada jotain järkeä siihen miksi virtuoosit ovat tehneet BASH:ista surkimuksen - selitän tätä siis itsellenikin: on pakko miettiä asiat paljon paremmin kun asiat kirjoittaa.

BASH:in ylipapit alkoivat jo yli kolme vuosikymmentä sitten toivoa että BASH hiljokseen häviää - syytä haluun en tiedä, mutta tosiasia on että BASH on niin monipuolinen ettei yksikään professori kykene hallitsemaan siitä isompaa osaakaan täydellisesti vaan oppilaat hyppivät silmille kokoajan - onhan se käytännössä pätevä syy yrittää päästä siitä eroon.

Mutta BASH oli siihenaikaan niin voimissaan ettei sen tuhoamisesta olisi tullut mitään - mutta mistähyvänsä pääsee eroon kun vaan antaa sen päättäjille riittävän löysän talutushihan niin he varmasti hirttävät siihen itsensä - ja tässätapauksessa siinä sivussa meinisi myös BASH. Hullulta tuntuva konsti toimii aina vaikkakin se on kamalan hidas - kaikkialla muuallakin käytetään tuota samaa keinoa  - sillä ei ole mitään sellaista joka ei hyödyttäisi jotakuta ja lähettäisi toiset manalaan.

Aluksi virtuoosit alkoivat sanoa että BASH on surkean hidas kaikssa muussa kuin tietokoneen hoitamisessa - mikä on täysin totta. Sitten pienen säätelyn jälkeen aletiin sanoa että useissa asioissa BASH on myös liian omituinen - sekin ihan totta. Virtoosit puhuvatkin aina varmasti totta joten esimerkiksi voi luottaa siihen että 'advanced guidet' puhuvat BASH:in alkeista ihan asiaa - pidemmäälle nuo oppat eivät edes yritä mennä huolimatta nimestään. Mutta ne esimerkiksi vihjailevat ettei BASH osaa käyttää nimiparamereja funktioissa - mikä on sekin yksi ohjelmointikielen menestymisen ehdoista. Ehkä ne itsekin uskovat väitteiseensä.

Tavallaan väite pitää kyllä paikkansa koska nimiparametrit eivät toimi BASH:issa samallatavoin kuin muissa kielissä - sillä kun BASH:issa passaat funktioon muuttujan käyttäen sen nimeä niin funktiossa se on tosiaan pelkkä nimi - kunnes se sidotaan saman-nimisen muuttujan arvoihin ja tyyppimääreisiin - tyyppimääreitä ovat sen arvot ja onko se tavallinen muuttuja vaiko tavallinen- tai assosiatiivinen matriisi - ja lisäksi niiden tarkenteet. Sitominen tapahtuu seuraavalla tavalla:

BASH pitää kirjaa muuttujistaan ja niiden senhetkisistä arvoista niinkuin muutkin kielet - ja BASH antaa kirjanpitonsa skriptaajan käyttöön käskyllä: declare. Kun kirjanpidosta löytyy sama muuttujanimi niin siinähän se muuttuja on argumentteineen ja kun määritelmät kopioi sieltä niin muuttuja on täysin kunnollinen - mutta jos jättää tämän sitomisen tekemättä niin nimiparametrit eivät toimi. Sitomiseen on muuttujakuvausten käyttämisen lisäksi pari käskyäkin: let ja read - jos oletetaan ettei käskyä: eval käytetä. Voiko olla sattumaa että kolme käskyä ja yksi menetelmä toimivat oikein asiassa johon niitä ei ole tarkoitettu? Mahdollisuus on pienempi kuin saada lotossa 10 oikein - kyllä ne on aikoinaan tarkoituksella tehty ja nimiparametreja osattu käyttää.

Samalla ratkeaa sekin ettei parametreja tarvitse palauttaa sillä jokakrran muuttujaa käytettäessä muuttujakuvausta muutetaan vastaamaan tilannetta - ja muuttujakuvaus on globaali elikkä sama kuvaus on käytössä kaikkialla - niin pääohjelmassa kuin jokaisessa funktiossakin - joten jos sitä muutetaan jossakin niin se muuttuu kaikkialla.

- senkin virtuoosit tekivät että he 'kielsivät' käyttämästä käskyä: eval - se nimittäin on helpoin ratkaisu myös yhteensitomiseen. Ja taas välittämättä virtuoosien puheista BASH:in kehittäjät ovat laittaneet tiedostoon: ~/.bashrc noin kolme eval-käskyä. Ketä uskoa?

Koetan selittää funktio-parametrien palautusta toisellakin tavalla: funktoista ei ole täyttä hyötyä elleivät funktiosta palattua sinne lähetetyt muuttujat ole muuttuneet. Tähän muuttamiseen on kaksi keinoa: muuttoksen suorittaa joko funktion kutsuja saatuaan tulokset funktiosta takaisin tai funktio itse toimintansa yhteydessä. Muissa kielisssä muutoksen tekee funktion kutsuja ja sitävartenhan parametrien arvot tulee palauttaa sieltä funktiosta. Mutta BASH ei toimi näin möllillä tavalla vaan muutoksen tekee funktio itse - tämä edellyttää että käytetään nimiparametreja ja että kielessä on kyky yhdistää nimi sen arvoon - BASH:illa on tuo kyky mutta muilla kielillä ei - mutta kyky ei riitä ellei sitä myös käytetä ja virtuoosit jättävät kylmän tyynesti kyvyn käyttämättä. Kun virtuoosit sanovat että BASH ei osaa parametreja palauttaa niin he puhuvat siis ihan totta - eikähän mikään laki vaadi kertomaan ettei BASH:issa parametreja tarvitsekaan palauttaa - mikäli on toimittu oikein. 

---

Ja 'nopeat komennot' nopeuttavat toimintaa paljon - nopeuttivathan ne aikanaankin mutta niiden käyttäminen romahti koska 'nopeat komennot' ovat nopeita vain kun skriptissä melkein kaikki käskyt ovat niitä nopeita eikä ilmeisesti kukaan huomannut sitä.

Toistaiseksi on liian aikaista edes arvella kuinka paljon ne nopeuttavat kokonaisuutta, mutta jo tähänasti tehdyt 'nopeita komentoja' hyödyntävät funktiot tekevät melkoisen kyky-loikan yksittäisissä tapauksissa - ja tekevät ainakin sen että BASH on surkea enää vain vähän. Ja on täysin varmaa että paljon lisää löytyy.

Jotta uusia ominaisuuksia voisi käyttää järkevällä tavalla täytyy niiden käyttämiseksi kirjoittaa funktio joka täytyy voida sijoittaa kirjastoon - mutta  virtuoosithan 'kielsivät' kirjastot? Ja taas BASH:in kehittäjät ovat asentaneet jokaiseen koneeseen itselleen merkittävistä toimista kirjastollisen funktioita - välittämättä virtuoosien 'kirjasto-kiellosta'. Ja eikö kehittäjä ole verrattomasti tietävämpi kuin virtuoosi?
- voit itsekin käyttää noita super-omituisia funktioita - esimerkiksi funktio nimeltä: quote palauttaa sille lähetetyn sanan lainausmerkeissä. Käske: quote antti -> tulostaa 'antti'

Ja BASH:ista yritetään muinkin keinoin tehdä surkimusta: esimerkiksi 'nopeat komennot' haudattiin uusien käskyjen alle ettei kukaan vaan huomaisi niiden käyttökelpoisuutta - ja muut keinot haudattiin muun roskan alle - samaa keinoa käytetään kaikkialla: hyväkin menetelmä hukkuu kun päälle sataa tarpeeksi roskaa. Toinen konsti on vaieta asia kuoliaaksi - eihän kukaan usko mihinkään sellaiseen josta virtuoosit eivät koskaan puhu.

Teoriassa BASH kykeneekin samoihin ohjelmointitöihin kuin muutkin kielet - hidashan BASH on eikä siitä taida nopeaa saadakaan - mutta pikkuinen toivonkipinä siitäkin on. Varsin omituinenkin BASH on. Käytännössä BASH on melkolailla toivoton kieli - mikä johtuu virtuoosien määräämistä rajoituksista joilla ei tunnu olevan kunnon syytä - mutta jos niistä ei välitä niin taivas tuntuu olevan rajana. Mutta 'kirjastokiellosta' ei oikein pääse eroon: kirjastot toimivat kyllä ihan hyvin, mutta 'kirjastokielto' estää kirjastojen lisäämisen perus-asennukseen - ja kirjastojen puute tuhoaa kielen ajanoloon takuvarmasti - ihme että BASH sinnittelee edelleen. Silti netistä löytyy vielä ainakin kymmenen isoa BASH-kirjastoa - unohtuneet nettiin ajalta jolloin kirjasto-osoitin vielä toimi?

Ja tuloksena tästä 'kirjasto kiellosta' on että olemattoman pieniinkin ongelmiin tarkoitetut skriptit ovat tuhatrivisiä hirviöitä jonka lauseet koostuvat sanoista jotka ovat todella inhottavia kirjoitus-asultaan joten niitä ei edes muista vaan ne täytyy jokakerran hakea itsetehdyistä tiedostoista.
 
Omaan koneeseensa voi toki laittaa itsetehdyn kirjaston - minun koneessani iso kirjastoni on toiminut moitteettomasti jo yli kahdeksan vuotta - vaikka koneeni ovat vaihtuneet usein ja myös Ubuntun versiot vaihtunet parikertaa vuodessa.

16
'nopeat käskyt' ovat paitsi nopeita niin niillä myös helppo määritellä nopeita ja monipuolisia toimintoja sillä ne eivät ole loogisia pommeja niinkuin uudet käskyt helposti ovat. Tosin vanha käskyt ovat vaikeasti muistettavaa merkki-sotkua. Esimerkiksi kun pyydetään:

kerro millä paikalla etsitty on hakulausekkeessa kun jossain haettavan jälkeen täytyy olla määrättävä sana:
Koodia: [Valitse]

merkkijono='abc def ghi jkl'; trigger=bc; arm=gh; etuosa="${merkkijono%%$arm*}";apu=${#etuosa}; [[ "${merkkijono:0:$apu}" =~ $trigger ]] && etuosa="${etuosa%%$trigger*}" && echo 'merkkino='$((${#etuosa}+1))
- tätä toimintoa varten on tehty myös regex - ja joku on puurtanut kuukausitolkkua kehittäessään sitä. Tämä tekemisessä meni parituntia - olihan tämä ensimmäinen laatuaan.
- kyse on aikaisemmin tuntemattomasta toiminnosta joten esimerkki on todennäköisesti huonosti valittu - mutta kannnattaa esittää sillä tiedähäntä mihin tämä johtaa.
- esimerkiksi tiedon etsimiseen rekistereistä tämäntapaisia tarvitaan - mutta BASH  on saanut niin huonon maineen hitaudestaan ja 'kiikkerästä' toiminnastaan etteivät luotettavasti toimivat 'nopeat käskyt' siihen minkäänlaista muutosta tuo.   


Tai sama haku hieman erilaisilla määrittelyillä: kerro millä paikalla etsitty on hakulausekkeessa kun haettavaa ennen täytyy jossakin olla määrättävä sana:
Koodia: [Valitse]

merkkijono='abc def ghi jkl'; trigger=bc; arm=gh; etuosa="${merkkijono%%$arm*}";apu=${#etuosa}; [[ "${merkkijono:$apu}" =~ $trigger ]] && etuosa="${etuosa%%$trigger*}" && echo 'merkkino='$((${#etuosa}+1))

- monipuolisemmillakaan hauilla nopeus ei juurikaan muutu.

17
Kirjastojen puutteen takia BASH:issa on runsaasti seuraavankaltaista: haluttaessa erottaa tekstistä joku sana käytetään yleensä seuraavantyyppistä toimintaa :
Koodia: [Valitse]
echo $text |  awk '{ print $3 }'       # BASH:in vastaava toiminto on:
matriisi=($text); echo ${matriisi[2]}  # ja se toimii kymmenkunta kertaa nopeammin. Onhan koodi vähän pidempi eikä ihan yleisesti
                                       # tunnettukaan. Mutta silti ihmettelen miksei sitä käytetä sillä virtuoosien on pakko
                                       # tuntea tuommoiset. Halutaanko vähätellä BASH:ia vaiko edistää awk:ia?
                                       # Mutta entäpä jos BASH:issa olisikin kirjasto ja siellä funktio:
                                       # function write () { matriisi=($1); echo ${matriisi[$2]} ;}. Silloin käsky olisikin:
write "$text" 2                        # Ja toiminto olisi edelleen melkein yhtä nopeaa.

-  käske: 
Koodia: [Valitse]
function write () { matriisi=($1); echo ${matriisi[$2]} ;}
käskystä jää sllähetkellä avattuna olevan päätteen muistin funktio - aivan niinkuin funktio olisi haettu kirjastosta. Käske sitten samassa pätteessä:
Koodia: [Valitse]
write "yksi lensi yli käenpesän" 2
-> tulostuu: yli .

- kyse on ajoista 4ms ja 0.5ms. Mutta ajetaanpa toiminto kuinka monesti tahansa samassa skriptissä niin toiminta kestää jokakerran melkein yhtäkauan. Ja kun samanlaisia pikkujuttuja on paljon niin koko BASH alkaa tahmaamaan. 
- voi käskeä nyös: set yksi lensi yli käenpesän; echo $3    # se on lyhyt ja nopea - niinkuin BASH taitaa olla aina jos ei hölmöillä.

18

Tai muunnos tieteellisestä esitysmuodosta normaaliin esitysmuotoon: 
Koodia: [Valitse]
function from_sci ()
{ nollia=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
kokonaisosa=${1%%.*} ; kokonaisia=${#kokonaisosa}
luku=${1//[.]/}
luku=${luku%%e*}
[[ ${luku:0:1} = - ]]  && { merkki=-; luku=${luku:1} ;} || merkki=''
exp=${1##*e}
 (( $exp > 0 )) && { luku=$luku$nollia; apu=$merkki${luku:0:$(($exp+$kokonaisia))}.${luku:$(($exp+$kokonaisia))};apu=${apu%%+(0)}; echo ${apu%.} ;} || { [[ -exp -gt $kokonaisia ]] && echo $merkki.${nollia:0:$((-$exp-$kokonaisia))}$luku || echo ${luku:0:$(($kokonaisia+exp))}.${luku:$(($kokonaisia+exp))} ;} ;}

# testausta ja suoritusajan määritystä  - yksi muunnos kestää luokaa 0.25 ms
time for expo in {-55..55}; do from_sci 123456789012345678901234567890123456890.12345678901234567901234567890123456789e$expo; done

19
Printf-käsky:llä on käynnissä ikuinen taistelu desimaalipisteen kanssa ja sillä lukujen koko rajoittuu 18 merkkiin. Kummankin puutteen voi poistaa 'nopeilla käskyillä' tehdyllä skrpteillä jotka osavat tulostaa  normaalissa esitysmuodossa annetun luvun tietellisessä esitysmuodossa tai päinvastoin - olipa luvuissa numeroita vaikka satoja - eikä desimaalipisteestä ole harmia:
Koodia: [Valitse]
function to_sci () { luku=$1
[[ ${luku:0:1} = - ]]  && { merkki=-; luku=${luku:1} ;} || { merkki=''; luku=${luku//+/} ;}
luku=${luku##+(0)}  # poistetaan etunollat - nimenomaan 0.xyx -> .xyz
apu=${luku%%.*}     # erotetaan kokonaiosa
exp=${#apu}         # lasketaan kokosasta positiivinen exponentti
[[ ${luku:0:1} = \[.,] ]] && { # katsotaan onko ensimmäin merkki desimaalipiste - silloin exponentti on negatiivinen
apu=${luku%%[1-9]*} # poistetaan kaikki siitälähtien kun ensimmäinen numero tulee desimaalipisteen jälkeisen nollasarjan perään. Siis tulos on desimaaipiste yksin jos nollia ei ole yhtään.
exp=$((1-${#apu}))  # lasketaan negatiivinen exponentti nollien lukumäärästä vähentäen yhden desimaalipisteestä
luku=${luku:1}      # palautetaan desimaaliosa jättäen desimaalipite pois
luku=${luku##+(0)}0 # poistetaa etunollat ja lisätään yksi peränolla
echo $merkki${luku:0:1}.${luku:1}e$(($exp-1)) # tulostetaan näin kun expnentti on negatiivinen - kokonaisosa on nyt ensimmäinen numero
} || { # halu dokumentoida aihuttaaa sen että ehtojen jälkeinen ryhmitys tulee rikkoa erotamalla nämä merkit tällätavoin
luku=${luku//[.,]/} # poistetaan desimaalipista sotkemasta
echo $merkki${luku:0:1}.${luku:1}0e$(($exp-1)) # tulostetaan näin kun exponentti on positiivinen - kokonaisosa on nyt ensimmäinen numero
} ;}

to_sci 1234567890123567890123456789012345678901234567890,1234567890111111111111111111111111111111111111111111111111111111111111111111
to_sci 1
to_sci +1
to_sci -1
to_sci .1
to_sci 0.1
to_sci -0.1
to_sci 10


- jos myöhemmin huomaa että muunnos toimii joskus väärin niin sehän olisi vain hyvä - joutuisi nimittäin korjaamaan ja ajukopan ränsistymistähän tässä koetetaan hidastaa.
- BASH:ia ei voi dokumentoidakaan kuten muita kieliä sillä ehtojen toinen tai kummatkin haarat saattavat olla koottuja lauseita ja mikäli ne kommentoi ninkuin normaalisti niin rakenne särkyy. Ei se kommentointi kuitenkaan raketti-tiedettä ole.
- BASH toteuttaa ilmaukset oikein silloinkin kun voisi vannoa ettei semmoista sotkua mikään pysty tulkitsemaan - joten skriptit lyhenevät ja nopeutuvat ikuisesti - tai onhan nollaa vaikeaa enää pienentää.
- nopeat käskyt' tosiaan ovat nopeita: näin monirivinen skripti on yhtänopea kuin yksi uusi käsky.

Muunnoksen kestoajan (noin .3 millisekuntia) määrittäminen:
alkuhetki=$(date +%s%N); to_sci 1234567890123567890123456789012345678901234567890.1234567890111111111111111111111111111111111111111111111111111111111111111111 ; loppuhetki=$(date +%s%N); aika=$((10#$loppuhetki-10#$alkuhetki-1000000)); apu=000000000$aika; apu=${apu: -14: -9}.${apu: -9}; echo ${apu##+(0)}
- printf "%e" 100000 kestää noin .2 millisekuntia

20
 
Käsitelläänpä sitten bc:

Kerro18 on huomattavasti nopeampi kuin bc - tosin kerro18 on vain 36 numeroinen liukuvanpilkun kertolasku. Samoin 72 numeron desimaalilukujen yhteenlasku on sekin nopeampi. Desmaalilukujen jakolaskukin toimii sekin nopeasti antaen noin 50 numeroa jotka yleensä kaikki oikein - valitettavasti eivät aina. Mutta sittenkin bc on ehdottomasti kunkku - nämä ovat vain vähäisiä säröjä bc:ssä.

Mutta esimerkiksi lukuja pyöristtessä bc on toistaitoinen: bc ei oikeastaan osaa pyöristää ollenkaan vaan se ainoastaan leikkaa sen desimalien lukumäärän määrämittaan. Ja sen leikkaamisenkin suorittamiseksi sen täyy tehdä jakolasku - se lasku voi kylläkin olla valelasku jossa jaetaan luvulla 1 joten mikään ei muutu. Mutta ihmiset eivät yleensä tiedä tätä eivätkä saa aina edes leikattua - ja taas saadaan lisää syytä mollata BASH:ia. Ja leikkaamiseenkin bc kuluttaa ylettömästi aikaa.

Mutta pyöristys-skripti pyöristää aina oikein ja on lisäksi salaman-nopea, 'kymmenenkertaa' nopeampi kuin bc:
Koodia: [Valitse]
function pyöristä () {
[[ ${1:0:1} = - ]]  && merkki=- || merkki=+
[[ $1 =~ \. ]] &&  desimaaliosa=${1##*.}000000000000000000 || desimaaliosa=0000000000000000000 # onko desimaalipistettä ...
kokonaisosa=${1%%.*}
apu=${desimaaliosa:0:$2}
desimaaliosa=$(($apu$merkki(( ${desimaaliosa:$2:1} >= 5 )) ))
echo $kokonaisosa.$desimaaliosa ;}

time pyöristä 1.22634 2          # tämä 'nopeilla käskyillä' toteutettu BASH-skripti kestää 0ms   
time bc<<<"scale=2; 1.22634/1"   # tämä bc:n lasku kestää 4ms - ja tulos on hieman virheelinen.
 
- tarkistelepa lausetta: $(($apu$merkki(( ${desimaaliosa:$2:1} >= 5 )) ))  -> BASH kokoaa ensin sellaisen tekstijonon kuin käsky määrää. Lähetettäessä tekstijono matematiikka-moottoriin sen osista jokainen määritellään sentyppisesti kuin hyvä tulee: siis jokainen osa voi olla tarpeen mukaan joko: tekstijono, numero, operaattori, laskutoimitus, funktiokutsu tai looginen arvo 0 tai 1 -> kaikki mitä sinne matematikka-moottoriin lähetetäänkin tuntuu toimivan.
- skandit funktion nimessä toimivat hyvin. Ei kyllä taida olla järkevää käyttää nimessä skandeja - mutta kokeillaan tämänkerran.

Sivuja: [1] 2 3 ... 33