Kirjoittaja Aihe: Skriptiajuri  (Luettu 126911 kertaa)

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #20 : 23.02.13 - klo:17.21 »
Kiitoksia suurtyöstä.

Olen monta kertaa jo harkinnut erilaisia tiedostonjako-palveluja sillä ne helpottaisivat kaikkien työtä ja samalla saisi kaiken siirrettyä. Mutta toivottavasti en siirry käyttämään niitä, sillä ne toisivat mukanaan kaikenlaisia oikopolkuja jotka myöhemmin johtaisivat vaikeuksiin. Foorumi pakottaa minut ruotuun.

Jossain vaiheessa saattaa kuitenkin olla pakko siirtyä niihin.

Samoin skriptiajuri täytyy nähdä käytössä, ei sen kuvaaminen onnistu.

Tomin

  • Palvelimen ylläpitäjä
  • Käyttäjä / moderaattori+
  • Viestejä: 11433
    • Profiili
    • Tomin kotisivut
Vs: Skriptiajuri
« Vastaus #21 : 23.02.13 - klo:20.27 »
Olen monta kertaa jo harkinnut erilaisia tiedostonjako-palveluja sillä ne helpottaisivat kaikkien työtä ja samalla saisi kaiken siirrettyä. Mutta toivottavasti en siirry käyttämään niitä, sillä ne toisivat mukanaan kaikenlaisia oikopolkuja jotka myöhemmin johtaisivat vaikeuksiin. Foorumi pakottaa minut ruotuun.

Minä näkisin, että niistä olisi huomattavaa hyötyä. Nuo palvelut on tehty avoimen koodin projektien käyttöön ja lähdekoodin hallintaan, joten en keksi miksi ne toisivat ongelmia. Enkä varsinkaan pidä nykyistä tapaa parhaana. Joka tapauksessa tee ihan niin kuin näet parhaaksi. Jotkut tavat vain ovat käyttäjälle yksinkertaisempia ja siten lisäävät kiinnostusta kokeilla.

Foorumillekin voi muuten lisätä liitetiedostoja viestiin. Tosin silloinkin tulee muistaa, että ne saatetaan myöhemmin tilan loppuessa poistaa.
Automaattinen allekirjoitus:
Lisäisitkö [RATKAISTU] ketjun ensimmäisen viestin aiheeseen ongelman ratkettua, kiitos.

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #22 : 05.03.13 - klo:21.33 »
Skriptiajuri alkaa saada ammattimaisia piirteitä sillä sen kuvaruudun päivitys nopeutui sadasta millisekunnista alle millisekuntiin koodin koon silti pienetessä. Skriptiajuri on muutenkin siinä vaiheessa jolloin koodia kannattaa alkaa kommentoida, huomautuksetkin lakkaavat ja toiminta vakavoituu muutenkin, koodin määrä laskee, kyvyt paranee .... Yleensä tuo kehitysvaihe edeltää sitä vaihetta jolloin koodi alkaa huonontua ja koko projekti kirpoaa käsistä.  

Skriptiajurin näppäinversio perustuu assosiatiivisiin matriiseihin, jotta siinä vaiheessa kun puheen tunnistus tulee Linuxiin saa puheentunnistuksen myös Skriptiajuriin.
***
Skriptiajurilla on erilaisia kykyjä ja jokaista kykyä vastaa oma sovellus. Kuitenkaan sovelluksia ei ennen kannattanut avata yhtaikaa sillä kaikkien sovelluksien nimeksi olisi tullut terminal ja olisi jatkuvaa näpyttely etsiä missä on se sovellus jota kaivataan, sillä sovelluksien järjestys menee vähänväliä sekaisin.

Vaan nykyään kaikki voi avata yhtaikaa sillä kaikilla avatuilla on oma nimi eikä enää ei ole pelkoa siitä että joku sovellus kaatuu ja sotkee järjestyksen. Samoin eri prosessien editorit puhuvat keskenään - leikepöytä ei enää ole ainoa tapa siirtää tekstiä. Esimerkiksi yhtaikaa voi avata monta skriptiajuria, haun miten joku asia on toteutettu muissa skripteissä, ohjekansion selaamisen, man-sivujen haun netistä ...

Tosin tällainen toiminta vaatii toistaiseksi jonkunverran käsin-tehtäviä asetuksia ja eri distrot toimii eritavoin.
**
Taas kertaalleen parantelin Skriptiajurin kykyjä näyttää man-sivuja. Suurin ongelma siinäkin on Linuxin äärettömyys: kaikista lukemattomista asioista on kirjoitettu lukematon joukko eritasoisia kuvauksia: roska on tietysti hautaa alleen kunnolliset kuvaukset, mutta se ei sittenkään ole se pääasiallisin syy. Pääasiallisin syy on se, että ihan päteviä virtuooseja on paljon ja kaikki he ovat muodostaneet oman koulukuntansa joka ajattelee kaikista asioista eritavoin.
Muistattekos vielä sitä aikaa kun kaikilla atk-professoreilla oli oma kielensä - tai ainakin kieliä oli Suomessakin kymmeniä ? Ja kaikissa kielissä pilkun paikkaa oli siirretty.
Ja C-kieli leviää; se pilaa BASH:in man-sivujakin.
**
Kykyjen lisäämisessä ei sinällään ole mieltä, sillä hyödyllisiäkin kykyjä on äärettömän monta ja mikäli niistä lisäisi edes pienen osan ei loputtomista valikoista loytäisi mitään nopeasti.
Skriptiajurinn kykyjen lisääminen onkin koe, kuinka helposti Skriptiajuriin saa lisätoimintoja - ja helppoa näyttää olevan. Ominaisuuksien lisäämisen helppous kertoo kuinka helppoa on räätälöidä Skriptiajuri käyttäjänsä tarpeisiin.
**
Netti on pullollaan ohjelmia joissa pääpaino on asetettu sille että ne ovat kauniin näköisiä ja nopeita. Nopeudellakaan ei tee mitään sillä esityskelpoisen lyhyehkön skriptin kasaaminen kestää viikkoja myös virtuoosilta vaikka virtuoosi väsää koodin muutamassa minuutissa - koodin väsääminen on pikkujuttu. Koska ohjelmat siis keskittyvät sivuseikkoihin niin ohjelmien elinkaari on yleensä: alkuun versio 0.01-alfa josta siirrytään melko nopeasti 1.00-betaan ja senjälkeen tulee muutama päivitys, ehkäpä tuotantoversiokin. Sitten iso hiljaisuus.

Skriptiajuri ei ole kaunis. Ja ennenkaikkea se on nippa-nappa riittävän nopea, mikrosekunti-nopeudet voit unohtaa. Mutta sen avulla tuon lyhyehkön skriptin saa esityskuntoon tunneissa. Skriptiajuri on myös ollut elossa jo kauan ja tämänpäiväinen päivitys on jossain lähellä sataa; esimerkiksi valikkohiirelle on versiota 2036 ja jokainen versio edellyttää kymmeniä kokeita - skriptiajuri tekee nopean kehittämisen mahdolliseksi. Päivitysseloste on sivulla:  http://forum.ubuntu-fi.org/index.php?topic=44605.msg342565#msg342565
**
Mikäli Skriptiajuria alkaa käyttämään skriptien tehtailemiseen kannattaa opetella avaamaan eri päätteet Skriptiajurille ja funltiolle "Etsi tekstistä" jolloin voit yhdellä tai kahdella hiiren kliksauksella siirtyä niiden välillä; etsitty sivu liittyy automaattisesti editointi-ikkunaan. Ei kannata sotkea työtiloja tähän ellei välttämättä tarvitse.
Esimerkiksi Mintissä itsenäisiä päätteitä voi avata niin monta kuin tarvitsee, Ubuntussa samaan päätteeseen voi avata uusia lehtiä (näpäytä hiiren vasenta pääteikkunassa ja valitse: avaa välilehti)
- terminaali näyttää siinä toimivan sovelluksen nimen omassa ikkunassaan kun kirjoittaa tiedostoon ~/.bashrc käskyn: trap 'echo -ne "\033]0;${BASH_COMMAND:15}\007"' DEBUG
- syy miksi Skriptiajurin ja "Etsi tekstistä" on hyvä olla auki yhtaikaa: kun Skriptiajurilla tekee uutta skriptiä tulee eteen ongelmia. Kannattaa hakea kuinka samankaltaisia ongelmia on aikaisemmin ratkaistu. Löytynyt sivu liitetään Skriptiajurissa editoitaviin sivuihin.
« Viimeksi muokattu: 20.03.13 - klo:06.24 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #23 : 17.03.13 - klo:07.36 »
Tämä konsti on käyttökelpoinen muidenkin sovelluksien kanssa, ei tämä Skriptiajuriin ole rajoittunut: kirjoita tiedoston ~/.bashrc loppuun:
alias usn='gnome-terminal --tab -t "Skriptiajuri" -e ~/OMATSKRIPTIT/"Skriptiajuri näppäimille" --tab -t "Etsi_tekstistä" -e ~/OMATSKRIPTIT/Etsi_tekstistä'
- ja boottaa sitten
tämänjälkeen kun kirjoitat päätteessä:usn avautuu yhtaikaa ikkuna skripteille Skriptiajuri ja Etsi_tekstistä ja voit siirtyä niiden välillä näpäytämällä otsikkoa
- mikäli vielä tiedostossa ~/.bashrc on: trap 'echo -ne "\033]0;${BASH_COMMAND:15}\007"' niin lehdillä on nimetkin eikä täydy kokeilla.

~/OMATSKRIPTIT/Etsi_tekstistä koodi:
Koodia: [Valitse]
#!/bin/bash
# Etsi_tekstistä etsii koko OMATSKRIPTIT tiedostopuusta mistä tiedostoista kysyttävä löytyy ja antaa mahdollisuuden lukea haluttuja
# tiedostoja yksi kerrallaan. Kaikki grepin määreet ovat haussa käytettävissä, siksi ohje.
# petteriIII 17.3.2013
reset # reset-käskyn tarkoitus on varmistaa, että päätteessä aloitetaan värit ja muukin perusarvoissaan
kanta=${0%/OMATSKRIPTIT*}; echo 'tätä skriptiä ajetaan paikasta: '$kanta # skripti ajetaan käskyllä: ~/OMATSKRIPTIT/Etsi_tekstistä  
. "$kanta"/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkonäppäimille # Valikkonäppäimille koodi liitetään tämän skriptin koodiin
. "$kanta"/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot1 # IDEfunktiot1 koodi liitetään tämän skriptin koodiin
. "$kanta"/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot2 # IDEfunktiot2 koodi liitetään tämän skriptin koodiin
while true
do
  etsiä_kysyttävää_ilmaisua_skriptien_tekstistä
done

- MINTillä muuten sama kunhan sanan: gnome-terminal vaihtaa sanaksi: mate-terminal
**
Skriptiajuri loistaa myöskin kehitettäessä ja tutkittaessa seuraavanlaisia:
joukko1=a5b9z; joukko2=1234567890zg; echo -n 'joukkojen leikkaus= '; tr -d $(tr -d $joukko1 <<< $joukko2) <<< $joukko2  
- jos joukoissa on välilyöntejä niin IFS kehiin.
- ja vastaaviahan on täysin ääretön määrä, eiköhän tähänkin löydy ziljoona erilaista keinoa.
- tämä tuo mieleen rinnakkaisprosessoinnin, joku tämmöinen kelpaisi sieluksi. Tiesittekös muuten että BASH:issa voi tehdä alkeellista rinnakkaisprosessointia jo nyt ?
- tuolla tavallahan sitä leikkausta ei lasketa, vaan esimerkiksi:
joukko1="yksi kaksi kolme neljä viisi"; joukko2="seitsemän neljä viisi kuusi seitsemän"; for n in $joukko1; do for m in $joukko2; do [[ $n = $m ]] && echo $n ; done; done
**
BASH ei ole nopea, sen käskyjen muoto-vaatimukset ovat mielipuolisia, omituisia salahautoja on kaikkialla ... BASH on ihan on nössö. Mutta BASH on aina riittävän nopea ja minkähyvänsä toiminnan saa aikaiseksi - mutta BASH vaatii toisenlaista ajattelua kuin muut ja kaikki onnistuu kunhan hintansa maksaa. Ennenkaikkea BASH opettaa hylkäämään huonot menetelmät ja muuttumaan jatkuvasti, sillä jos et muuta käsityksiäsi kokoajan niin huomaat varsin nopeasti etteivät konstisi enää pure.

BASH on haastava sillä joudut kilpailemaan itsesi kanssa.  
**
Skriptiajurissa haku-toiminnoilla on oma historia-tiedostonsa, jossa on pelkästään ne sanat joita on haettu. Tämä tiedosto vaihdetaan haettaessa Linuxin historiatiedoston paikalle eikä toimintaa muuteta muuten mitenkään joten historian kanssa voi toimia ihan samallatavoin kuin normaalistikin; selata nuolinäppäimillä, etsiä ctrl-r:llä tai !? keinolla. Mutta koska kaikki haettavat ovat niitä sanoja joita on etsitty ei tarvitse penkoa paljoakaan kun haettu löytyy eivätkä haetut "pääse kätkeytymään isoon joukkoon". Kun haettu on näytöllä voi sitä editoida.
**
BASH on ihmisille liian liukas käsiteltävä. Monista esimerkeistä yksi pahimmista: BASH:in merkistöön kuuluu myös merkkejä, jotka eivät näy mutta muuttavat BASH:in toimintaa. Virtuooseiltakin kestää pitkään tajuta miksi kahdesta ulkonäöltään aivan samanlaisesta käskystä toinen toimii ja toinen ei, ja vasta-alkajalle syy ei selviä koskaan. Korjaamiseen on yksi yksinkertainen ratkaisu: ellei käsky ole tajuttoman pitkä niin kirjoitetaan kaikki uudestaan oman koneen näppäimillä varoen hipaisemastakaan mitään mikä ei ole tarpeen; esimerkiksi kosketuslevy aiheuttaa paljon vikoja.

Ajaaskel puhui tästä jo vuosia sitten ja vaikka asian tajusinkin niin en osannut aavistaakaan kuinka vakavasta ongelmasta oli kyse; ja ilmeisesti ongelma pahenee kokoajan kun "uusia toimintaa helpottavia pika-valintoja" lisätään.

Mitä enemmän tuota kontrollimerkki-ongelmaa tutkin niin sitä enemmän alkaa tuntua siltä, että vian nimi on hiukan väärin sillä eivät ne invalidisoivat merkit
ole varsinaisesti kontrollimerkkejä vaan editorien lisäämiä "kontrolli-merkkejä" jotka yleensä alkavat: M-

Näiden "kontrolli-merkkien" metsästämiseen sopii parhaiten käsky: cat -v skriptitiedostonNimi
- tai jos etsii "kontrollimerkkejä" tekstijonosta löytää ne käskyllä: echo "tekstijono" | cat -v
- jos skriptin listaus olisi muuten kovin pitkä voi sitä rajoittaa: cat -v skriptitiedostonNimi | grep M-   . Se selventää muutenkin.
**
Asensin Skriptiajuriin mahdollisuuden piirtää käyriä piirto-ohjelmalla nimeltään: gnuplot . Gnuplotin saa asennettua käskyllä: sudo apt-get install gnuplot gnuplot-X11 evince
Kokeen tarkoituksena oli selvittää kuinka helposti skriptiajuriin saa piirto-ohjelman ja sekoittaako se jotain: itse skriptiajuri ei piirto-ohjelmaa tarvitse.
Toimivan skriptin kasaamisessa oli melkoinen työ. Koodi oli tämä:
  gnuplot <<_EOF_
    set term postscript enhanced color
    set output 'tiedoston_nimi_polkuineen.eps'
    set title 'testResults'
    p 'tiedoston_nimi_polkuineen' u 1:2 w l  # tiedoston riveillä on: x-arvo [välilyönti] y-arvo
_EOF_
evince tiedoston_nimi_polkuineen.eps # evincen tilalla voi olla myös imagemagic

# muuten gnuplot osaa myös 3D piirtämisen jne.
**
Nyt lienee aika tunnustaa miksi aloin tehdä Skriptiajuria: näin vanhemmiten muisti on kadonnut lähes täysin. Esimerkiksi mielessä ei kestä hetkeäkään mihin pitää laittaa välilyönti ja mihin sitä ei saa laittaa. Samoin huomasin ratkaisevani samoja ongelmia jatkuvasti. Loopin kasaaminen oli painajaista. Nyt Skriptiajuri muistaa puolestani - ja lisäksi se muistaa muidenkin tekoset.

Samoin sillä on kyky tajuta "itsestäänselvyyksiä". Esimerkiksi Skriptiajurin myötä tajusin käyttää käskyä: read -e $1   . Näin käskyn olemassaolon selvittyä on helppo käsittää, että tottakai se onnistuu funktiossa kun $1:ssä on muuttujan nimi.
- tämä on muuten esimerkki myös siitä kuinka funktio palauttaa arvon - ja eiköhän arvo voi olla matriisikin.

Skriptiajuri muuten toimii minkä kielen kanssa tahansa. Ainoastaan skriptien ajaminen ei onnistu ennenkuin koodia on vähän muutettu.function muodosta_Skriptiajurin_tiedostorakenne () {
mkdir -p $kanta/OMATSKRIPTIT/ARKISTO/{SKRIPTIT,DOKUMENTIT,HISTORIAT,ASETUKSET,APUTIEDOSTOT}
mkdir -p $kanta/OMATSKRIPTIT/{"KOE- JA ESIMERKKISKRIPTIT",FUNKTIOKIRJASTO,OHJEITA}/ARKISTO/{SKRIPTIT,DOKUMENTIT,HISTORIAT}
echo "OMATSKRIPTIT" > $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/KansionNimiAloituksessa
echo 1 > ~/OMATSKRIPTIT/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa
touch ~/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö
}
**
Päivitin 2.4 lähes kaikki Skriptiajurin koodit. Koodien koot ovat pienentyneet  ja toiminta nopeutunut ja sujuvoitunut. Päivitysseloste on sivulla:  http://forum.ubuntu-fi.org/index.php?topic=44605.msg342565#msg342565
- tarkistettu toimivaksi yhdellä koneella.
- muuten vaikka koodi onkin pitkä toimii kaikki 'ennenkuin kerkiää kättään napilta nostaa'.
**
Luovuin Skriptiajurin käyttö-ohjeista - teen edelleen lisää käyttöohjeita mutta niiden käyttäminen painottuu toisin kuin ennen. Sillä kuten kaikilla muillakin sovelluksilla käyttöohjeet ovat paisuneet niin että jo niiden näkeminen vie uskon että koskaan oppisi sovellusta edes välttävästi käyttämään. Eikä teoria kiinnostakaan vaan esimerkkejähän sitä kaipaa. Ja niitähän skriptiajuri on pullollaan.
**
Olen viimepäivinä testannut millaisia tuloksia skriptiajurilla saa - siis kuinka tehokkaasti se pystyy asioita etsimään ja avustamaan niiden toimintaan soveltamisessa. Kohteeksi otin ajaaskelen md5sum-skriptin sentakia että ongelma on helppo ymmärtää eikä BASH:illa saa aikaiseksi  mitää käyttökelpoista siinä työssä, niin luulin.

Ensimmäiseksi ulkonäöltään aivan toisenlainen ratkaisu kuin ajaaskelella. Sen toiminta oli yhtähidas.

Sitten taulun laskeminen assosiatiiviseen matriisiin. Se toimi aika kivasti ja matriisin saattoi tallettaa levylle ja käyttää myöhemmin sitä levyllä olevaa. Nopeus taulukon teossa oli yhtä surkea kuin normaalistikin, muuta lukeminen oli aika nopeaa kun taulukon koko oli pieni.

Rinnakkaisprosessointi (jossa oli muutama rivi logiikkaa) osoittautui kaksiteräiseksi miekaksi ja suorituskyky kasvoikin sillä korkeintaan nelinkertaiseksi ja yleensä vain vähän. Ja yleensä se sekoitti järjestyksiä - tosin en kokeillutkaan varsinaisia rinnakkaiprosessointi-ohjelmia kuten esimerkiksi parallel.

Sitten kokeilin kuinka tuo "rainbow haku" toimisi BASH:illa kun käytettävissä on valmistaulukko. Haku toimi epämiellyttävän nopeasti. C-kieli kuutamolle sillä BASH hoitaa homman yhtänopeasti - no menihän siinä muutama sekunti giga-kokoisella taulukolla, eikä aavistustakaan kuinka nopea C olisi mutta eihän tuossa juurikaan parantamisenvaraa ole.
**
Minkähyvänsä skriptin suoritus lakkaa painettaessa CTRL-c ja silloin toiminta palaa päätteeseen. Esimerkiksi skriptin villiintyessä tai mennessä tilaan jossa minkään napin painaminen ei tee mitään saa koneen palaamaan päätteeseen kun painaa CTRL-c.
Skriptiajuri omii tuon CTRL-c:n itselleen ja niinpä painettaessa CTRL-c paluu tapahtuukin skriptiajuriin ja skriptiajurihan alkaa aina samasta paikasta jossa se oli skriptin suorituksen alkaessa elikä se palaa skriptin valintaan tuo villiintynyt skripti valittuna - niinkuin tarve yleensä onkin.
Onhan se tietty mukavaa että joutuu painamaan muutamaa nappia vähemmän, mutta suurin merkitys on siinä ettei tarvitse siirtää "ajatusjunaansa hetkeksi toisille raiteille"; ei se prosessinvaihto ole pieni homma aivoillekaan.
- skriptit voivat silti ottaa CTRL-c:n tarvitessaan itselleen.
- jotkin skriptit saavat koneen sellaiseen tilaan ettei CTRL-c lopeta toimintaa tai tekee jotain vallan muuta. Tällöin seuraavaksi kannattaa kokeilla CTRL-z:taa. Myös päätteen lopetus saattaa toimia (se x ylärivin oikeassa kulmassa). Mutta mikäli mikään muu ei auta niin kun painaa: ctrl-alt sysreq ja nämä napit pohjassa näppäilee hiljokseen REISUB  niin kyllä tokenee. Niin tokenee myös kun painaa virtanappia - virtuoosit huutaa kyllä kauhusta jos tämmöistä edes ehdottaa.
**
Sktriptien koodia ei voi suojata niin ettei sitä näe. Ohjelmointi-putiikit eivät edes harkitse BASH:in käyttämistä, sillä rahat täytyy saada ja tuo suojaamattomuus on tabu. IBM kyllä teki aikoinaan jotain pientä mutta tarkoituksena oli vain kiusata Mikrosoftia - se oli sitä aikaa kun Mikrosoft tosissaan pelkäsi Linuxia.

Aikoinaan BASH:ille tehtiin ohjelma joka kääntää sen koodin c-kielelle. Ohjelma olikin varsin suosittu. Ohjelma ei edes yrittänyt nopeuttaa koodia vaan sen yksinomainen tarkoitus oli suojata koodi niin ettei sitä nähnyt. Ohjelman tukeminen loppui jo kymmenkunta? vuotta sitten sillä BASH on jokatapauksessa ihmisille liian vaikea käytettävä - tai siis oli sillä kunniallista IDE:ä ei ennen BASH4:ää voinut tehdä.
**
Skriptiajurinkin virheet paljastuvat helpoiten kun sillä kokoajan tekee jotakin. Sitäpaitsi se on mielenkiintoista: BASH on armottoman hidas, mutta sillä saa tuloksia samassa ajassa kuin paremmilla kielillä kuluu ongelman kuvaamiseen. Bash ei olekaan ohjelmointikieli vaan ongelmankuvauskieli - ja kun sillä on kuvannut ongelman niin se toimiikin jo.
**
Piti kirjoittaaa ohje debuggaamisesta. Mutta sitten luin: debuggaaminen on vaikeampaa kuin koodaaminen. Jos et saa aikaan virheetöntä koodia niin kuinka debuggaaminen onnistuu senkään vertaa ?

Kesäksi täytyy siirtyä muihin hommiin ja jättää skriptiajuri.  Saa nähdä onnistuuko siirtyminen ja syksyllä paluu skriptiajurin kehittämiseen; vähän pelottaakin mutta onhan tämä jo toinen paussi. Toisaalta jos jotain haluaa tosissaan kehittää niin näin täytyy välillä tehdäkin, sillä etäisyys tuo esiin muutostarpeita.
**
Debuggaukseen voi suhtautua mitenkävain, mutta skriptin käyttäytyminen virhetilanteissa täytyy ehdottomasti olla kunnossa. Skriptiajuri ilmoittaa virheistään mukavasti ja olenkin ihmetellyt miksi se ilmoittaa virheistään niin hyvin sillä olen tehnyt asian vuoksi hyvin vähän. Vaan kyllähän minä olen tehnyt: BASH 4:ssä virhekäsittely on puoliautomaattinen käytännössä merkityksellisimpien virheiden suhteen ja vaatii vain että funktio command_not_found_handle on asianmukaisesti määritelty - useimmiten virheet päätyvät nimittäin tilanteeseen jossa yritetään suorittaa olematon käsky tai tunnettu käsky virheellisillä parametreilla.
**
Tein skriptiä jolla saa muutettua sanan toiseksi kaikkialla määrättävässä tiedostojärjestelmän osassa. Vasta kun aloin miettiä mitenkä skriptiajuri neuvoi vastaavanlaisia skriptejä muodostamaan tuli ahaa-elämys:
find polku -type f -exec sed -i "s/mikä/miksi/g" {} \;  
- kääntävien kielien käyttäjille: tulkki muodostaa noista ohjeista "miljoonia rivejä jollakin käännettävällä kielellä". Mikäli skriptissä on rivejä vain yksi toimii kokonaisuus  melko nopeasti.
- tämmöisiä massa-muuttaja-skriptejä ei saa käyttää ellei koneessa ole *hyvää* backup-järjestelmää.
**
Skriptiajuri on hyvä kehitysympäristö. Mutta yksinään skriptiajurikaan ei ole mitään, ei sittenkään vaikka sillä olisi paljon käyttäjiä. Mutta skriptiajuri on myös itseoppiva tietokanta - skriptiajuri oppii kun sitä käytetään. Tietokantansa kautta skriptiajuri on kosketuksissa internettiin ja toisiin skriptiajureihin.
**
BASH:ia vaivaa sekin, että toiminnoista pystyy etsimään tietoa vasta sitten kun tietää toiminnallisuuden olemassaolosta. Apropos ja apt-search kun ovat melkein tuntemattomia.
Esimerkiksi käsky compgen; kerro kaikki vaihtoehdot kuinka käskyn loppu voisi olla. Kun esimerkiksi tiedostopuun kansio- ja tiedosto-nimet voivat olla mielivaltaisen pitkiä ja sisältää välilyöntejä ja erikoismerkkejä onkin tiedostolistauksen ottaminen vaikeaa. Mutta sen saa yksinkertaisesti käskyllä: compgen -fd <kansio> . Mutta jos et ole "keittiön kautta" kuullut käskystä compgen jää se kyllä käyttämättä sillä etsimällä et sitä löydä.  
Käsky compgen on hyödyllinen monissa muissakin tehtävissä. Samanlaisia käskyjä on ziljoona; olet ehkä kuullut että Linuxin käskykannalla ei ole rajaa ?
**
Yritän saada tietoa aiheesta "hidden environment variables". Niitä on melkoinen määrä mutta tietoa niistä ei äkkiseltään löydy.
**
BASHin pahin vika normaali-käytössä on se että siinä on kaikkea liikaa ja koska ihminen ei pysty käsittelemään kovin suuria kokonaisuuksia on kaikki jaoteltu lukemattomiin paikkoihin. Etsiessään tietoa jostakin ei nopeasti voi edes päätellä mistä pitäisi etsiä ja kun jotain löytää on se pilalle yli-dokumentoitu. Yli-dokumennoin vaikutuksia Skriptiajuri pystyy vähentämään paljon eikä Skriptiajurille merkitse mitään että kaikkea on liikaa vaan se löytää etsittävän jos se on olemassa.
- googlaamalla löytää asioita hyvin eikä tarvitse paljoakaan googlailla ennenkuin oppii mikä on "asiaa" ja mikä roskaa. Mutta sen määritteleminen mikä "asia" on tosiaan oikein ja hyvin esitetty kestää melkoisesti. Sensijaan skriptiajurin tietojen laatu on melkohyvä.
**
Skriptiajuri tuntuu toimivan Ubuntu 13.10:ssä.
**
Aloin tehdä sitä editorin tukemaa skriptiä sanan muuttamiseksi toiseksi määrättävässä tiedostojärjestelmän osassa ja "kuningaspultti" onkin jo valmis. Työ on suuri, sillä olen oppinut jo luottamaan siihen että BASHista löytyy mitähyvänsä ja kannatta etsiä sillä nopeutusta tulee vähintään satakertaisesti ja koodista tulee erittäin pieni. BASH-Linux on tosiammattilaisten tekemä.
**
Skriptiajurin tarkoitus on muuten se, että kun joko sinä itse tai maailmalla joku muu on ratkaissut jonkun homman ei samaa tarvitse koskaan enää tehdä uudelleen vaan voit etsiä kyseisen ratkaisun.

Hyvin toimiva kyseinen toiminto on aivan liian suuri tehtävä minun toteuttaa eikä minulla ole tarpeellisia kykyjäkään. Silti jo nykyinen Skriptiajuri on minulle itselleni erittäin hyödyllinen.
**
Skriptiajurin koodi vaati seuraavaa muutosta jotta se toimisi vaikka näyttöjen rivinpituus vaihtelisi monikymmenkertaisesti:

Tekstijono jossa on sama merkki toistettuna monta kertaa (repeat-string):
RivinPituus=$(tput cols); PuolenRivinpituudeltaPlussia=$(eval printf '+%.s' {1..$(($RivinPituus/2))}); echo $PuolenRivinpituudeltaPlussia
- tuo $(tput cols) laskee näytön rivinpituuden huolimatta siitä millainen näyttö on ja ottaa huomioon mikä on näyttö-ikkunan koko.
- tuosta pitkästä käskystä on helppo karsia käytössä riittävä palanen; esimerkiksi voit tulostaa perättäisiä plussia tai pikkuisella muutoksella mitähyvänsä: printf '+%.s' {1..55}
- kuitenkin perättäiset miinukset: printf -- '-%.s' {1..55} ja perättäiset jakoviivat:  printf "/%.s" {1..55} -> siis lainausmerkit kovista pehmeiksi
**
Heti tuli eteen uusi ongelma: luotaessa uusi näyttöikkuna tai siirrettäessä vanhojen paikkoja muuttuvat vanhan ikkunan asetukset  ainakin vähän jolloin ne pitää tehdä uudelleen.
**
Skriptiajuri ei koskaan tuhoa mitään, sillä joskus kelvottomissakin skripteissä on jotakin hyvää. Ja kovalevyltä kaikki tekstimuotoiset hommat vievät mitättömän vähän tilaa joten kaiken voi säilyttää.

Esimerkiksi tein aikoinaan skriptin nimeltä: palautuspiste. Koska se käyttää sellaisia menetelmiä joiden käyttämisen "Ubuntu" vuosia sitten esti ei skripti enää toimi. Mutta ei skriptiä tuhotakaan kannata sillä siinä on paljon käyttökelpoistakin. Mutta ei sitä valittavienkaan joukossa kannata pitää koska sitä ei saa valita.

Ratkaistakseni ongelman tein jokaiselle kansiotasolle kansion nimeltä ARKISTO/POISTETUT johon kaikki sen kansiotason kelvottomat skriptit siirretään ettei niitä suotta esitettäisi valittavien joukossa.
 
« Viimeksi muokattu: 24.06.13 - klo:07.19 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #24 : 27.06.13 - klo:16.41 »
Skriptiajuri ei koskaan tuhoa mitään, sillä joskus kelvottomissa ja toimimattomissakin skripteissä on jotakin hyvää. Ja kovalevyltä kaikki tekstimuotoiset hommat vievät mitättömän vähän tilaa joten kaiken voi säilyttää.

Esimerkiksi tein aikoinaan skriptin nimeltä: palautuspiste. Koska se käyttää sellaisia menetelmiä joiden käyttämisen "Ubuntu" vuosia sitten esti ei skripti enää toimi. Mutta ei skriptiä tuhotakaan kannata sillä siinä on paljon käyttökelpoistakin. Mutta ei sitä valittavienkaan joukossa kannata pitää koska sitä ei saa valita. Ratkaistakseni ongelman tein jokaiselle kansiotasolle kansion nimeltä ARKISTO/POISTETUT johon kaikki sen kansiotason kelvottomat skriptit siirretään ettei niitä suotta esitettäisi valittavien joukossa mutta että ne löytyisivät tarvittaessa.
**
BASH on toivottoman hidas varsinkin jos sen edistyneempiä toimintoja ei käytetä. Mutta se ei ole syy siihen ettei BASH:ia käytetä vaan todellinen syy on se ettei sitä kukaan hallitse: toimiva skripti on usein helppo tehdä, mutta nopea ja oikein toimiva skripti on melkein mahdoton tehtävä.  

"Salahautojen" takia BASH ei olekaan kieli jossa kirjoitetaan vaan kieli jossa kopioidaan. Useimmiten kopioidaan itseltä sillä toisten tekemissä skripteissä on merkityksellistä vain ne ideat johon se perustuvat - skriptit eivät useinkaan edes toimi ja moitteettomia ne ovat erittäin harvoin.

Ja kuitenkaan BASH:issa ei juuri koskaan käytetä kirjastoja vaikka kirjastoa käytettäessä ei tarvitse vaivautua edes kopioimaan. Ilmeisesti BASH on piikki kehittäjien lihassa, sillä kirjasto-osoitin poistettiin käytöstä ja se tekee kirjastojen käytöstä vaikeaa.
**
Toistaiseksi on järkevää ainoastaan tehdä rutiini joka ilmoittaa kun skriptissä on kontrollimerkkejä. Kontrollimerkkien automaattinen poistaminen taitaisi olla hölmöä sillä ainakin joitain niistä tarvitaan aina ja jotkut aikaansaavat toivottuja ilmiöitä. Kenties joskus tulevaisuudessa kun skriptiajurin tietokanta on paljon suurempi voi analysoida kontrollimerkkien merkitystä ja tehdä poistorutiinin.
- kaikki kielet kärsivät näistä merkeistä jossain määrin: esimerkiksi BOM (?) joka kertoo kuinka seuraavat merkit tulkitaan, onko käyttöjärjestelmä big- vai low-endian, Widows/Linux vai Apple.
**
Jokainen uusi sukupolvi hylkää edellisen sukupolven tekemisistä kaiken sillä vanhoilla tavoilla saa hitaasti aikaiseksi hitaita skriptejä. Tämä johtuu siitä ettei missään kerrota kuinka ne hyvät skriptit kootaan. Ja hyvät keinot ovat kymmeniä kertoja kertoja parempia kuin huonot - ja on suurinpiirtein varmaa ettei kukaan niitä hyviä keinoja yksikseen löydä eikä löydä edes isossa joukossa. Aikoinaan yritettiin keksiä keinot löytää niitä hyviä tekomenetelmiä mutta epäonnistuttiin surkeasti. Mutta nyt asiat ovat toisin: netti pursuaa niitä hyviä menetelmiä ja BASH-4 mahdollistaa niiden kokoamisen.

Tehtäessä skriptejä ei kirjoiteta omasta muistista mitään, vaan kaikki kopioidaan netistä kootusta tietokannasta - tarkoitus olisi että voitaisiin kopioida poikkeuksetta sillä poikkeukset palauttavat siihen vanhaan tapaan skriptata ja se johtaa hitaaseen kyvyttömien skriptien tekemiseen.  

Kopiointi edellyttää hyviä hakumoottoreita. Skriptiajurin hakumoottori onkin hyvä sillä se on tehty seulomaan sitä sekamelskaa josta BASH-skriptit muodostuvat. Mutta sekään ei riitä sillä vaikka hakumoottorille voikin antaa rajoittavia haku-termejä niin silti vastauksia tulee liikaa. Mutta hakumoottori osaa myös rajoittaa haku-paikkansa niihin joista löytyvät parhaat vastaukset - ja skriptiajuri puolestaa osaa muodostaa hyviä hakupaikkoja.
**
Työtilat saa unohtaa skriptiajurin kanssa sillä vaikka virtuoosit eivät kärsikään niiden omituisuuksista niin noviiseille ne ovat ylipääsemätön paikka.

Käyttöjärjestelmän ikkunointia käyttävä järjestelmä taas toimi niin mallikkaasti että kehitin sitä melkoisesti. Mutta kun lopussa vertasin sitä itsenäiseen skriptiajuriin niin itsenäinen skriptiajuri oli parempi.
**
Tulipahan kokeiltua eri pääteohjelmia ja mitä tapahtuu kun esimerkiksi gnome-terminalin poistaa. Oli muuten pikkuisen kolkko tunne kun näennäisesti päätettä ei ollut. Xterm alkoi kuitenkin ajaa skriptiajuria ilman että tarvitsi tehdä mitään.

Muuten Mintistä poistin mate-terminalin ja varmistuttuani että Xterm toimii siinäkin asensin pääteohjelmaksi gnome-terminalin. Hyvin sekin toimi.
**
Skriptiajuri on nyt vähän aikaa vain testauksessa ja samalla onkin aikaa hyödyntää sen ominaisuuksia kirjaston parantamisessa. Kirjastoon alkaakin kertyä hieman korkeamman tason käskyjä kuten esimerkiksi "ei ihan triviaaleja" matriisi-operaatioita ja niiden dokumentaatioita.
**
Toisilta ei koskaan kopioida vaan kopioidaan vain omia tekosia. Mutta tämä on yksinomaan yritystä suojautua huonolta koodilta. Ideoita sensijaan voi "kopioida" toisilta täysin vapaasti sillä alunperin ideat ovat Linuxin kehittäjien ja hehän ovat antaneet ideansa yleiseen käyttöön. Joten jos joku yrittää omia muka itse kehittämiään ideoita niin syyllistyy rikolliseen tekoon. Rikollista noissa yrityksissä on olla kertomatta että "copyright" koskee yksinomaan kirjoitus-asua; ja siinäkin yritetään "copyrightata" toisten omaisuutta.
 
- esimerkiksi käsky: awk '!a[$0]++' joka tulostaa tiedoston jättäen pois samanlaiset rivit on näennäisesti kovin keksinnöllinen. Voit kuitenkin olla täysin varma siitä että awk:in kehittäjät ovat suunnitelleet awk:in toimivan myöskin noin ja että tuokin käsky olisi mahdollista kehittää itsekin kunhan hankkii "awk-kirjoitustaidon" vuosien työllä. Kova työ, kieltämättä. Mutta pyörän keksimistä uudelleen.

Mutta edes ideoita ei kannata käyttää sellaisenaan vaan yrittää käsittää kuinka ne toimivat, testata ja muokata niitä loputtomiin. Lisäksi toimiakseen ideat vaativat yleensä tukea monilta muilta ideoilta.
**
BASH:in merkintätavat ja logiikka ovat vieraasta maailmasta. Muissa kielissä ongelma ei ole yhtä paha, ja niissä kirjastot vielä pienentävät ongelmaa. BASH osaa sekin käyttää kirjastoja ja itseasiassa sille on tehtykin lukemattomia kirjastoja - kirjastoja joita vartioidaan mustasukkaisesti, niiden koodi salataan paketteihin koettaen väittää että homma on jotenkin "mun kehittämääni".
**
Skriptiajuri kehittyy kyllä kokoajan, mutta se on saavuttanut vakaan vaiheen ja tekee kokoajan sitä tehtävää johon se on tehty; se nopeuttaa skriptintekoa "kymmenkertaisesti".

Mutta ennenkaikkea skriptiajuri mahdollistaa uudentyyppisten skriptien tekemisen: vaikka BASH:illakin täytynee olla rajat niin minä en ole löytänyt niitä. Ja kun ongelma on niin vaikea ettei sitä millään kielellä saa ratkaistua alkaakin BASH tuntua mielekkäältä: vaikka BASH onkin hidas niin on parempi saada tulos BASH:illa kuin ei ollenkaan.
**
Älä anna BASH:in nykytilan hämätä: edesmenneillä virtuooseilla on ollut käytössään todella edistyksellisiä skriptejä. Mutta nuo skriptit on toimimattomina päästetty häviämään sillä maailman muuttuessa noihin skripteihin olisi täytynyt tehdä vastaavat muutokset eikä kukaan ole muutoksia osannut tehdä; ei se uus-kyvyttömyys mitään uutta ole.

Myös kauan sitten itsetekemäni skriptit ovat kaikki menneet käyttökelvottomiksi Ubuntun muuttuessa ja niiden korjaaminen toimiviksi on aikaisemmin osoittautunut liian työlääksi. Mutta skripti-ajuri on muuttanut senkin: noiden vanhojen skriptien korjaaminen on osoittautunut nopeaksi ja ennenkaikkea varmaksi; koska työtä ei tarvitse alkaa tehdä ajatellen "kuinkahan tässä käy ja paljonko aikaa tuhraantuu" niin korjaamisesta tulee "vähemmän epämiellyttävää" ja nopeaa.
**
Saycy testattu käytettäessä btrfs-tiedostojärjestelmää. Skriptiajuri toimii kaikissa suhteissa. Samoin tarkistin että kaikki toimii käytettäessä EFI:ä ja GPT:tä. Muuten kaikki toiset skriptit eivät toimi  kun joku näistä on paikalla.
**
Varsinaisia virheitä ei ole tullut vuoteen mutta jatkuvaa testaustahan tämä on samoinkuin kosmeettisia muutoksia. Ja kohtahan tulee BASH:in seuraava versio.
Se ominaisuus on huippu-kätevä että kun tehtävä skripti villiintyy niin tuon villiintyneen skriptin voi kaataa tahallaan ctrl-c:llä tai jollain ja silloin palataan heti skriptiajuriin siihen pisteeseen jossa oltiin ennen villiintymistä. Skriptiajuri itse ei ole moksiskaan vaikka painelisit ctrl-c naama punaisena.
**
ohje kuinka Skriptiajurille tehdään kuvake työpöydälle: http://forum.ubuntu-fi.org/index.php?topic=42023.msg323640#msg323640. ohje on pysynyt toimivana jo puolitoista vuotta - se on iäisyys Ubuntu-vuosissa.
**
Tehty 14.04/64bit/btrfs:n vaatima muutos. Korjasin Skriptiajurin Skriptiajurissa sillä se on ylivertainen korjauksessakin. Minulla ei ole selvää käsitystä mikä aiheutti väärin tulkkaamisen, mutta skriptiajurin näytöstä oli helppo päätellä missä tarvitaan muutosta ja minkä kaltainen sen täytyy olla. Muutoksen jälkeen kaikki vanhakin toimii.
**
Skriptiajuri kannustaa kopioimaan. Mutta koodia kopioidaan vain itseltä, ei koskaan toisilta. Tämä on tismalleen sama kuin se että ryhmä tekee ohjelman nopeasti ja se aikaansaa huomattavasti enemmän kuin hyväkään koodari - mutta taas kun mennään todella edistyneisiin ohjelmiin niin ne ovat yksinäisten "super-koodarien" tekemiä.
Ideoita "kopioidaan toisilta": on täysin mahdotonta olla kopioimatta sillä kaikki on tehty jo aikoja sitten - "super-koodaritkin" tekevät yleensä jotakin joka on tehty jo monesti ennen.
**
19.11.13 jälkeen en ole tehnyt skriptiajurille mitään muuta kuin tarkistanut sillointällöin sen toimivuuden; voiko edelleen tehdä uutta ja korjata vanhaa, toimiiko versionhallinta, toimiiko 14.04:ssa, toiminta btrfs:ssä jne. Toiminnassa ei ollut mitään huomautettavaa.
- tosiaan senverran uutta että aloin kirjoittamaan elämänkertaani. Soveltuu Skriptiajuri näemmä siihenkin. Muuten versionhallinta on rautaa kaikissakin blog-tyyppisissä kirjoituksissa.

« Viimeksi muokattu: 23.01.14 - klo:14.49 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #25 : 02.03.14 - klo:18.44 »
Skriptiajurin kehittämiseen tuli pakko-tauko. Tämä on ensimmäinen ponneton yritys aloittaa taas.
Foorumilla kysyttiin äskettäin kunka saada toimimaan bash-käsky mallia: a=1; b=100000; echo {$a..$b}. Vastaus on: a=1; b=100000; eval echo {$a..$b} .
- tuota eval-käskyä suomitaan kaikkialla "kehityksen jarru-sivuilla" bash-hackers:ista gregs-wikiin. Niissä ei vaivauduta selittämään miksi ja vaikeaa se olisikin sillä käsky toimii luotettavasti - muualta löytyy viittauksia tietoturvaan varsinkin silloin kun koheltaa.

Esimerkiksi yksi toimiva ja usein käytetty versio on: a=1; b=100000; for i in $(seq $a $b); do echo -n $i' '; done
ja se toimiikin ihan hyvin eikä käskyn hitaus näy yleensä missään. Kuitenkin tällainen tulos saadaan vain koska mitattaessa suoritusaikaa time-käskyllä real-osaa pidetään lähes ainoana merkitsevänä osana tuloksessa. Kuitenkin user- ja ennenkaikkea sys-osat kertovat mikä nopeus olisi jos esimerkiksi näytön päivitykselle ei annettaisi merkitystä. Mittaa itse minkä nopeutuksen sisäisen eval-funktion käyttäminen antaa ja tulkitse sinnepäin kuin pitäisi: nopeutuksen ala-raja on noin 30% ja ylä-raja useampi kymmenkertainen. Kumpikin on vain osa-totuus.

Tuo seq-käskyn hitaus ei merkitse sitä ettei sitä pitäisi käyttää, sillä pienissä käytöissä se on ihan hyvä, mutta jos totutaan käyttämään vain sitä ei päästä koskaan isompiin hommiin käsiksi. Sama koskee kaikkia muitakin ulkoisia käskyjä. Ja ettei kävisi liian yksinkertaiseksi niin BASH:han on niin hidas ettei se kykene oikeastaan mihinkään ilman ulkoisia ohjelmia. Täytyy siis harkita koska ulkoisia ohjelmia käytetään.


- pari muutakin käytettyä menetelmää on:
a=1; b=100000; for (( n=$a; n<=$b ; n++ )); do echo -n $n' '; done                
a=1; b=100000; until [ $a -gt $b ]; do echo -n $a' '; ((a++)); done    

ja mikäli alkaa etsimään erikoisia toteutuksia niin niitä on rajattomasti niinkuin esimerkiksi:
mawk 'BEGIN{for (i = 1; i <100000 ; i += 1) print i}'   tai:
set {1..100000}; echo $@
**
Pienien skriptien tekeminen on helppoa, mutta skriptien koon kasvaessa vaikeudet kasvavat eksponentiaalisesti. BASH on kuitenkin tarkoitettu isoihin skripteihin. Tämä näkyy esimerkiksi siitä, että pienissä skripteissä historia on niin merkityksetön etteivät useimmat ole kuulleetkaan koko käsitteestä BASH:in yhteydessä mutta isossa skriptissä historia tulee ehdottomasti olla kunnossa - esimerkiksi kännyköissä ja tektinkäsittelyjärjestelmissä historia on ilmanmuuta eikä historiatonta järjestelmää edes hyväksyttäisi. BASH:issa historia on toteutettu käyttöjärjestelmän tasolla joten ominaisuudet ovat loistavat eikä ohjelmointia tarvitse sovellustasolla tehdä juuri ollenkaan.

Samoin lokit saavat skriptin koon kasvaessa kokoajan lisää merkitystä; esimerkiksi jokainen skriptaaja moittii BASH:in virheenkäsittelyä mutta kyllä se ihan kevollinen on - se vaan toimii lokien kautta ja oletkos edes kuullut kenenkään koskaan käyttäneen lokeja skriptien virheekäsittelyssä ? BASH käyttää runsaasti muitakin käyttöjärjestelmäpalveluja skriptiä kehitettäessä: on koodin syntaksin-tarkistusta, debuggereita, tunnettujen muuttujien tulostusta ja vaikka mitä; ne ovat kylläkin usein omituisina versioina sillä BASH:in logiikka on omituista.
« Viimeksi muokattu: 05.03.14 - klo:14.35 kirjoittanut petteriIII »

nm

  • Käyttäjä
  • Viestejä: 16232
    • Profiili
Vs: Skriptiajuri
« Vastaus #26 : 02.03.14 - klo:19.18 »
Testataanpa.

Koodia: [Valitse]
a=1; b=100000; eval echo {$a..$b}
Jos ohjaan tulosteen /dev/null-tiedostoon, jotta terminaalin hitaus ei vaikuta suoritusaikaan, time antaa tällaiset ajat:

real  0m0.118s
user 0m0.108s
sys  0m0.008s


Tämä versio on huomattavasti hitaampi, kuten sanoit:

Koodia: [Valitse]
a=1; b=100000; for i in $(seq $a $b); do echo -n $i' '; done
real   0m0.724s
user   0m0.696s
sys   0m0.032s


Pelkkä seq-käsky on kuitenkin varsin nopea. Hitaus tulee siitä, että kutsut silmukassa echoa 100 000 kertaa. Kokeile sen sijaan vaikka tätä versiota, joka tuottaa saman tulosteen:

Koodia: [Valitse]
a=1; b=100000; seq -s " " $a $b
real   0m0.043s
user   0m0.040s
sys   0m0.000s
« Viimeksi muokattu: 02.03.14 - klo:19.20 kirjoittanut nm »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #27 : 02.03.14 - klo:21.13 »

Pelkkä seq-käsky on kuitenkin varsin nopea. Hitaus tulee siitä, että kutsut silmukassa echoa 100 000 kertaa. Kokeile sen sijaan vaikka tätä versiota, joka tuottaa saman tulosteen:

Koodia: [Valitse]
a=1; b=100000; seq -s " " $a $b
real   0m0.043s
user   0m0.040s
sys   0m0.000s


Tottapa turiset. Täytyypä tutkia huomenna.

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #28 : 03.03.14 - klo:06.24 »
Millainen kone sinulla on nm ?

Onko missään hyvää kuvausta time-käskystä, kuinka sen arvot tulkitaan ja kuinka paljon arvot saattavat vaihdella koneiden välillä ?

nm

  • Käyttäjä
  • Viestejä: 16232
    • Profiili
Vs: Skriptiajuri
« Vastaus #29 : 03.03.14 - klo:13.53 »
Millainen kone sinulla on nm ?

Prosessori on Intel Core 2 Q9550, kellotettu 3,4 GHz:iin.
Ubuntu 12.04.

Onko missään hyvää kuvausta time-käskystä, kuinka sen arvot tulkitaan ja kuinka paljon arvot saattavat vaihdella koneiden välillä ?

Arvot voivat vaihdella hyvinkin paljon eri järjestelmien välillä riippuen siitä millaista suoritusta mitataan. Tässä tapauksessa aikaan vaikuttavat vain komentotulkin (ja coreutils-ohjelmien) versio sekä prosessorin nopeus, jos skriptin tuloste ohjataan /dev/null-tiedostoon:

Koodia: [Valitse]
time ./skripti.sh > /dev/null
Jos ohjausta ei tehdä, skripti tulostaa päätteeseen niin paljon tavaraa, että päätteen hitaus kasvattaa reaalisuoritusaikaa.

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #30 : 15.06.14 - klo:19.10 »
Skriptiajuri on aina kaivannut yhtä osaa, mutta sen toteuttaminen oli aikanaan liian vaikeaa ja olisi kestänyt monta viikkoa täysiä päiviä. Mutta kun nyt olen oppinut toimimaan skriptiajurissa niin aloin tehdä tuota palikkaa - skriptiajuria kun käytännössäkin editoidaan itsellään. Saunaan oli kiire joten aikaa oli käytettävissä vain varttitunti. Täytyy kyllä tunnustaa että kyllä saunan jälkeenkin tuli loppuhiontaan käytettyä viisi minuuttia.
**
Skriptien ajaminen tökkii, mutta kun teet Skriptiajurille oman kutsun niin senjälkeen saat aina käynnistettyä Skriptiajurin ja Skriptiajurilla taas voit käynnistää minkähyvänsä ajokelpoisen BASH-skriptin teoriassa mistähyvänsä samasta koneesta.
- hae seuraava koodi johonkin tiedostoon koneessasi. Kannattaa kopioida koodi heti, sillä kun mählii pilaa se todennäköisesti koko tiedoston.
- onhan se versio 2:kin jossain mutta tällähetkellä tämäkin toimii.

[Desktop Entry]
Version=1.0
Type=Application
Terminal=true
Icon[fi_FI]=bash
Exec=gnome-terminal --window --maximize -x bash /home/petteri/OMATSKRIPTIT/Skriptiajuri
Name[fi_FI]=Skriptiajuri
Name=Skriptiajuri
Icon=bash

Muuta polku ja tiedostonimi oikeiksi EXEC=... rivillä. Muuta tiedoston nimeksi: Skriptiajuri.Desktop  . Anna tiedostolle suoritusoikeus. Kuvake muuttuu heti eikä tiedostoa tämänjälkeen enää pysty edes avaamaan joten jos siinä on virhe niin roskikseenhan se joutaa. Raahaa kuvake työpöydälle.
- kuvakkeen saa sitten raahattua työpöydältä Dashboardiin (=palkki vasemmassa reunassa).
- huomioi muuten että kun tiedostolle on annettu suoritusoikeus niin sitä ei enää voi editoida. Jos haluat editoida sitä tai tehdä toisen niin hae foorumilta uusi käynnistindesktop_-tiedosto tai tee kopio kuten aikaisemmin.
- jos ikonin ulkonäkö ei muutu nimenvaihdoksen jälkeen ja kone urputtaa "ei ole trusted" niin kenties suoritusoikes on tippunut pois. Anna se.
- tarkistaa myös  että sana Desktop on kirjoitettu suurella.
- ennen koodia olevat kommenttirivit tulee poistaa samoinkuin koodin jälkeisetkin ennenkuin nimi muutetaan.
- kunhan muuttaa skriptin nimen niin kyllä tämä muidenkin skriptien kanssa toimii.
 
« Viimeksi muokattu: 15.03.15 - klo:06.08 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #31 : 10.08.14 - klo:11.58 »
Ohjeita skriptiajurin hakemiseksi koneeseesi:
- siirtolinkki ei näy ennenkuin kirjaudut foorumille.
- siirto lähtee käyntiin kun näpäytät liitetiedoston kuvaketta. Lataus suuntautuu kotikansiosi kansioon: Lataukset
- klikkaa foorumilla skriptiajuri.tar.gz:ää ja avautuvasta ikkunasta: 'tallenna tiedosto' jolloin koneesi Lataukset-kansion ilmestyy tiedosto nimeltään OMATSKRIPTIT.tar.gz. Näpäytä sitä hiirellä  ja avautuvasta ikkunasta Pura ja taas avautuvasta ikkunasta Pura. Ainoastaan kansio OMATSKRIPTIT tulee lisää.
- siirrä OMATSKRIPTIT-kansio koti-hakemistoosi.
- raahaa työpöydälle OMATSKRIPTIT-kansiossa olevat kuvakkeet: Skriptiajuri ja Skritiajurihiirelle
- siirrä OMATSKRIPTIT kansiosta kuvake skriptiajuri kansioon Työpöytä.
- jos haluat vain kokeilla skriptiajuria niin skriptiajuri lähtee koneestasi kokonaan kun poistat OMATSKRIPTIT-kansion eikä skriptiajurista silloin jää jäljelle kuin muisto.
- skriptiajurin käyttöön tarpeellisia ohjeita saat kun skriptiajurissa painat f3.
- skriptiajurin dokumentti taas ilmestyy kun painat f4.
- skriptiajurin käynnistimen saat kun purat käynnistin.tar.bz2:n
- tai toinen konsti skriptiajurin käynnistämiseksi on käskeä: ~/OMATSKRIPTIT/\Skriptiajuri

lisäsin skriptin PelastaData. Tämä skripti tutkii ensin mitä kaikkia massa-muisteja löytyy ja liittää sitten ne kotikansioon jossa niiden tutkiminen on helppoa. Vielä helpompi kuin Nautilus on Nemo jossa painamalla f3:a avautuu näkymä kahteen tiedostopuuhun joten datan kopioinnista eri kovalevyjen välillä tulee todella helppoa.
Ja mikäli skriptin laittaa boottavalle muistitikulle voi muistitikulla bootaamalla tutkia sellaisenkin koneen kovalevyn joka ei enää boottaa. Kummalliset tiedostojärjestelmät saattavat kylläkin vaatia Ubuntuusi asennettavan uusia paketteja - mutta sitten onnistuu vaikka WINDOWS tai Apple.

Samoin lisäsin skriptin palautuspiste joka kopioi järjestelmän muut levyt kaikkine osioineen kopiointilevyn tiedostoksi josta ne voidaan palauttaa joko alkuperäisille tai toisille levyille. Uusien kohdelevyjen ei tarvitse olla samaa tyyppiä kuin alkuperäinen, mutta ainakin yhtäsuuria. Kohdelevyjä ei tarvitse osioida eikä alustaa - itseasiassa mitä siellä onkin tulee jyrätyksi osiotaulua myöten. Mutta uudet levyt tulee asentaa aivan samoin kuin entisetkin. Kohdelevyt boottaavat jos alkuperäinen on bootannut, grub toimii niinkuin ennenkin eikä sillä ole väliä mitä kopioidaan - Windowsia en ole kokeillut mutta pitäisi sen onnistua. fsck saattaa vaatia lisäpalikoita jotta vieras tiedostojärjestelmä tunnettaisiin mutta dc3dd ei niinkään; jopa androidista höpistään. Tällä työkalulla saa kerättyä kaiken lukukelpoisen tiedon vialliselta kovalevyltä, myös poistetut siirtyvät mutta ne täytyy edelleenkin un-deletoida.

Yritän kokoajan saada skriptiajuria täysin järkiinsä sen jäljiltä kun sitä supistettiin sata-megaisesta nykyiseen noin 400kiloon. Mutta ei se pelkkää tuskaa ole ollut sillä kyllä se on myös selvittänyt asioita.
**
Aloin kasata Kovalevy_funktiot kirjastoa. Toistaiseksi sen helmi on käsky Osioselvitys joka määrittelee:

muuttujat: osiojollaollaan kotiosio
matriisin: tunnetutosiot
assosiatiiviset matriisit: osion_levy    osion_label    osion_UUID   osion_tiedostojarjestelma

- siis esimerkiksi: echo ${osion_levy[$osiojollaollaan]} tulostaa bootti-levyn nimen.
- olen aina ihastellut BASH:in muotoiluohjelmaa. Normaaleja format-määrittelyjä saisi antaa parituhatta ennenkuin pääsisi samaan. Eipä silti, tässä column-ohjelmassa taitaa olla paljon useampia. Ja sen käyttäminen on vaivatonta.
**
 Skriptiajuri käyttää erittän runsaasti funktiokutsuja. Funktiokutsu vie aikaa parikymmentä mikrosekuntia, joten skriptiajurille funktiokutsut eivät merkitse mitään ja olemattoman vähän muillekin skripteille.

Funktiomäärittelyjä ei välttämättä tarvitse kirjoittaa tehtävään skriptiin silloinkaan kun kirjastopolkua ei ole annettu, sillä skriptiajuri käy hakemassa ne kirjastosta automaattiseti ja liittää koodiin. Funktiot saavat kutsua toisia funktioita.

Automaatti lataa myös käyttöjärjestelmään skriptin tarvitsemat paketit - esimerkiksi jos skripti tarvitsee toimiakseen esimerkiksi pakettia btrfs-tools.
**
Syynä skriptauksesta luopumiseen on kuulemma siinä, että skriptien koodia voi lukea, kopioida tai lisätä jotain vahingollista. Skripteile onkin tehty monia käntäjiä juuri tästä syystä sillä skriptit ovat sinälläänkin riittävän nopeita - ei ne kääntäjät muuten toimi kunnolla vaikkei niitä sittenkään saa kynsiinsä.

Koodin lukeminen ja muuttaminen voitaisiin estää skriptiajurissa ja lisäksi tulisi vielä se etteivät skriptiajurin skriptit edes toimisi kopioituina ellei skriptiajuri toisin määräisi. Skriptiajuri oli aikoinaan tämmöinen mutta sitten havaitsin että suojauksista on harmia esimerkiksi silloin kun "ei virtuoosi" joutuu hoitamaan skriptiajuria ja saa koneensa täyteen skriptejä joita ei voi käyttää mutta ei saa deletoituakaan.

Skriptiajuri pystyy ajamaan skriptin silloinkin kun skriptillä ei ole suoritusoikeutta. Jos skriptiltä viedään kirjoitusoikeuskin sitä voi ajaa mutta ei muuttaa. Jos skriptiltä viedään lukuoikeus ei sille voi tehdä mitään, mutta kyllä se mukana kulkee ja nimikin näkyy tiedostopuussa - ja kun lukuoikeus palautetaan alkaa skriptikin toimia. Mutta tuo edelläkerrottu suojaustapa tekisi sen ettei edes pääkäyttäjä voisi skriptille mitään, oikeinsovellettuna ei voisi edes lukea.
**
Asensin 15.04:n EFI-lle, gpt-levylle ja btrfs-tiedostojärjestelmälle. Skriptiajuri toimi silläkin ihan kivasti. Käyttöjärjestelmällä tuntuu kyllä olevan vaikeuksia.
**
Aikaisemmin tehdyn manuaalisen roskankeruun avuksi lisäsin automaattista roskankeruuta. Roskaa muodostuu vähän jos toimitaan niinkuin pitäisi, mutta roskaa jää järjestelmään paljon mikäli toimitaan väärin; nämä rutiinit ovat siis jonkunsortin itsensä-korjaamista.
**
Tehtäessä uusia skriptejä löytyy sovellus-ohjeita lähes kaikkeen - esimerkiksi myös man-sivuilta löytyy paljon tarpeelisia ohjeita, mutta siellä ne ovat sellaisessa muodossa että vain aivonsa nyrjäyttänyt tajuaa ne säällisessä ajassa kun sensijaan omat ohjeet selventävät kaikille.

Skriptiä tehdessä ei voi sählätä kovinkaan pahasti eivätkä skriptitkään pysty ryppyilemään mitenkään sillä skriptiajuri pitää kaiken tiukasti hyppysissään: jos tehtävä skripti ei toimi niin sitten se ei vaan toimi ja koodia täytyy editoida. Mutta jos tehtävä skripti villiintyy tai hirttää kiinni voi sen tappaa ctrl-c:llä mikä ei edes hidastaa kokeilemista. Tai voihan sen skriptin häiriköinnin lopettaa myös sulkemalla koko koneen, siirtää kovalevyn toiseen koneeseen tai repiä liittimet irti, mutta semmoinen kyllä hidastaa vaikkakaan ei kovin paljon.

Olen viimepäivinä yrittänyt löytää sellaista mitä ei voisi BASH:illa ratkaista. Enpä ole vielä onnistunut mutta merkinnöistä kylläkin tulee aina vaan mielipuolisempia kun ratkaisu monimutkaistuu viikkojen kuluessa - siis aikaa kuluu näin kehitysvaiheessa tolkuttomasti mutta onnistuminen on varmaa.
Skriptit ovat alkuunsa lähes aina hitaita moni-kymmen-rivisiä ja sitten rivit alkavat rajusti vähetä ja toiminta nopeutua. Väitetään ettei skriptejä pitäisi optimoida, sillä samalla ne menettävät selväpiirteisyytensä. Mutta esimerkiksi seuraavaa skriptiä optimoidessa selvisi missä järjestyksessä tehtävät tulee suorittaa jotta skripti olisi nopea ilman optimointiakin ja silti se on selväpiirteinen:

Koodia: [Valitse]
#!/bin/bash
function tulosta_parametri () {
monennestako_parametrista_alkaen=$1
montako_tulostetaan=1 # tähän voi kirjoitta minkä luvun haluaa
#echo ${@:(-monennestako_parametrista_alkaen):montako_tulostetaan}  # perästäpäin laskettuna
echo ${@:monennestako_parametrista_alkaen+1:montako_tulostetaan}    # alustapäin laskettuna
}

tulosta_parametri 11111 {99999..1} # suomenkielinen seloste käskystä: tulosta 11111:s jäsen joukosta: 99999 99998 ... 3 2 1

- tehtäessä skriptejä skriptiajurilla funktioita ei täydy kirjoittaa itse, sillä skriptiajurikin osaa hakea tarvittavat funktiot ja liittää ne koodiin. Kun skripti on yhden kerran ajettu skriptiajurilla on koodi toimintakelpoinen muissakin koneissa.
**
Koko shellshock-episodin aikana skriptiajuri on kokoajan toiminut täysin moitteetta, myös sen export. Mutta matematiikka-funktiot on vielä kummallisempi: se muodostuu yksinomaan ympäristöön määritellyistä funktioista - ja sekin on kokoajan toiminut täysin moitteetta, myös 15.04:n kanssa. Kuulemma tilanne on toinen kun BASH-funktioita kutsutaan muista kielistä.
- täytyy tarkentaa: kaikesta päätellen paikkauksien olisi pitänyt vaatia muutoksia koodiin. Mikseivät ne vaatineet?
**
En ole tajunnut kertoa mistä skriptiajurissa on kyse: toimimisesta yksinomaan siinä koneessa jonka näppäimet ovat käytettävissä ja toimimisesta niin yksinkertaisilla palikoilla kuin mahdollista. Tämä ei kokonaan estä verkkokäyttöä, mutta kaikki ulkoiset palikat se sulkee pois jos niitä ilmankin pystytään toimimaan, kaiken "silmäkarkin" se kieltää samoinkuin PPA:t, pilvet ja sensellaiset. Ja ainoastaan puoli-grafiikka on sallittua. Internetistä tietoa saa hakea vain leikepöydän kautta.
**
Toistuvat tehtävät on tarkoitus suorittaa funktioissa. Toistot (loopit) kannattaa myös muodostaa funktiossa. Esimerkiksi:
function Kertaa () { MontakoKertaa=$1; shift; for n in $(seq $MontakoKertaa); do $@; done;}; Kertaa 5 echo "echon paikalle voi laittaa minkähyvänsä käskyn tai funktion"
- ajettaessa skripti skriptiajurissa funktiomäärittelyn voi jättää pois; siis tämä on yksinkertainen loopin muodostustapa.
**
15.04:ssä gconf-editor on jätetty perusasennuksesta pois ja se täytyy nyt ladata erikseen. Ja gconf-editor on muutenkin muuttunut ja se vaatii muutoksia koodiin. Ja Gedit:istä tulee kohta uusi versio ja sen vaatimat muutokset taitavat aiheuttaa nikotusta.


« Viimeksi muokattu: 29.05.16 - klo:11.55 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #32 : 02.01.15 - klo:03.59 »
Teetpähän koneessasi mitähyvänsä niin eteen tulee seuraavankaltaisia ongelmia: juuri äskettäinhän minä tein seuraavan-ja-seuraavan, mutta en totisesti muista mihin sen talletin. Kyseiseen ongelmaan on monenlaisia ratkaisuja mutta tässä yksi jossa esitetään aikajärjestyksessä kaikki mitä olet tehnyt ja mistä ne löytyvät:

find kansio_josta_listaaminen_alkaa -type f -print0 | xargs -r0 stat -c '%.19z %n' | grep -v mitkä_rivit_vain_sotkevat_ja_jotka_voi_poistaa | grep -v määritelmiä_voi_olla_monta | sort

esimerkiksi: find ~/OMATSKRIPTIT -type f -print0 | xargs -r0 stat -c '%.19z %n' | grep -v /ARKISTO/ | grep -v .*~ | sort

- kaikkikin nämä etsintämenetelmät auttavat käytännössä vain kun niitä käytetään usein, sillä harvoin käytettyinä niiden käyttö-tavat unohtuvat eikä niiden tuloksiakaan osaa kunnolla tulkita. Skriptiajuri auttaa oleellisesti.
**
Lähinnä tämä on osoitus siitä kuinka BASH on ajettu nurkkaan lukemattomilla tempuilla vaikka BASH on erittäin käyttökelpoinen joissain tehtävissä.

Tämä on tehty erään loistavan artikkelin pohjalta. Loistavan ? Vaikka käytössäni oli kunollinen kehitysympäristö niin kesti aamusta iltaan kokoaikaista työtä muuttaa tuon artikkelin ideat tämmöiseen puolittain käyttökelpoiseen muotoon - sillä tuskinpa tämäkään on sellaisenaan käyttökelpoinen kenellekään. Ja vaikkakin skriptin mukaeleminen kunnon kehitysympäristössä onkin helppoa niin kehitysympäristön käyttö ei oikein onnistu ennenkuin oivaltaa BASH:in toimintatavat - esimerkiksi sitä että BASH on ohjelmageneraattori eikä sen pitäisi koskaan toimia itse. Ja että kaikkiin ongelmiin on monia ratkaisutapoja - ja ettei BASH käytä niistä yhtäkään vaan sillä on ihan oma tapansa.

Tämän skriptin tarkoituksena on osoittaa että tehokkain tapa passata matriisi parametrina on passata sen nimi. Skripti kertoo myös kuinka matriisia käytetään, sillä vaikka esimerkki on tulostamisesta niin kyllä muukin käyttö on samanlaista.
Tämä skripti osoittaa taas kertaalleen että vaikka kaikkiin ongelmiin on monia ratkaisutapoja niin BASH ei käytä niistä yhtäkään vaan sillä on ihan oma tapansa.

- käskyä eval kehotetaan monilla verkkosivuilla olemaan käyttämättä mutta syytä ei kukaan ole kertonut. Nyt monen vuoden jälkeen Gregs wiki kertoi: syynä on että väärinkäytettynä eval on turvallisuus-riski. Sitä onkin ihan hyvä olla käyttämättä initialisointi-skripteissä varsinkin servereissä. Näin harrastelijan työaseman käyttö-skripteille se on täysin kelvoton syy.

Koodia: [Valitse]
#!/bin/bash
x[10]=aaaaa; x[11]=bbb; x[12]='"ccc ccc"'; x[13]=d; x[777]=eeeeee ; alku=2; montako=3
# Matriisin nimen, jäsenten lukumäärän ja osoitteiden arvot voi muuttaa haluamikseen, sillä funktio käy läpi osoitetun matriisin osoitealueen järjestyksessä alhaalta ylös ja tulostaa vain määritellyt jäsenet; siis määrittelemättömiä jäseniä ei tulosteta mitenkään.

function TulostaMatriisi () {
echo Matriisin $1 'arvot: '; [[ ! $(eval echo \${$1[*]}) ]] && echo matriisi on määrittelemätön && return
[[ ! $2 && ! $3 ]] && [[ $(eval echo \${$1[*]}) ]] && eval echo -n \${$1[@]} && return
[[ $2 && $3 ]] && [[ $(eval echo \${$1[*]}) ]] && eval echo -n \${$1[@]:$2:$3} && return
[[ ! $3 ]] && [[ $(eval echo \${$1[*]}) ]] && eval echo -n \${$1[@]:$2} && return
$(eval echo \${$1[*]}) ]] && eval echo -n \${$1[@]::$3}
}

TulostaMatriisi x                             # koko Matriisin tulostus
#TulostaMatriisi x alku montako                # tulostus alun määräämästä jäsenestä montako jäsentä eteenpäin
#TulostaMatriisi x 0 montako                   # tulostus Matriisin alusta montako jäsentä eteenpäin.
#TulostaMatriisi x alku                        # tulostus alun määräämästä jäsenestä Matriisin loppuun
                                               
#x=( "${x[@]}" )                               # BASH:in matriisissa voi alussa tai keskellä olla määrittelemättömiä jäseniä. Näin poistetaan määrittelemättömät jäsenet
#x=( "${x[@]::$alku}" "${x[@]:$((alku+1))}" )  # alku:n osoittaman jäsenen palauttaminen määrittelemättömäksi ja heti perään määrittelemättömän jäsenen poisto.

**
Sainpa tehtyä skriptiajuriin automaattisesti päivittyvän "bookmark" toiminteen jolloin on nopea siirtyä äskettäin tehtyjen skriptien välillä - nimittäin skriptiä tehtäessä tulee usein tilanteita joissa täytyy siirtyä tekemään toista skriptiä kokeillakseen mitenkä jokin asia tehdään. Sillä olen huomannut että minkä hyvänsä tekemiseen löytyy yksinkertainen konsti mutta että se täytyy usein kehittää itse.
Opinpahan lisäämään rivin tiedoston ensimmäiseksi riviksi. Ja opin että siihen voi ehdottomasti luottaa että käytännössä toimivaksi havaittu olisi aina oikein vaan että on aina syytä tarkistaa mitä man-sivuilla kerotaan.
**
Skriptiajuri särkyy ellei tee massa-siirrotkin itse skriptiajurissa . Mutta nautilus on virtuoosien pitkän työn tulos ja loppuunsa asti hiottu. Siksi varsinkin massa-siirrot tulee helposti tehtyä sillä ja luotettua siihen että skriptiajuri korjaa itsensä - mutta eihän mikään korjaus aina toimi. Skriptiajurin tiedostoselain alkaa olla monissa tehtävissä nautilusta parempi joten houkutusta alkaa olla helpompi vastustaa. 
**
Muisti kultaa kaiken. Mielestäni keskipoikkeaman laskentaan tekemäni awk-skripti toimi hyvin. Joissain tilanteissa se kyllä toimikin, mutta ei yleisessä tapauksessa. Kyllä skriptiajuri on kiva kun sillä löytää helposti keskeneräist työt ja saa etsittyä ohjeet saattaa työ loppuun.
**
jatkuvasti uusia käyttöähelpottavien ominaisuuksien lisäämistä. Kuitenkaan käyttö ei vaikeudu ollenkaan jos ei uusia ominaisuuksia käytä - lisäksi mikään lisäys ei saa havaittavasti hidastaa tai muuttaa mitään.  Skriptiajurista on kehittynyt kaksiulotteinen automaattinen alias-järjestelmä.
**
editoinnin automaattisesti päivittyvä bookmark-tiedosto osoittautui niin käyttökelpoiseksi että tein oman bookmark-tiedoston myös ajetuille skripteille.
**
Työpöydällä oleva käynnistin ei ole automaattisesti suurentanut ikkunaa enää aikoihin. Eilen aloin etsiskellä syytä ja niitä löytyikin monta: aivan alkuun se ettei dconfeditor enää kuulu alussa ladattaviin ohjelmiin. Rarkaisuksi täytyi ottaa työpöydälle sijoitettavan käynnistimen muuttaminen. Käynnistimen kuvaus löytyy sivulta:
http://forum.ubuntu-fi.org/index.php?topic=44605.msg363468#msg363468
**
teinpä skriptin jonka nimi kokonaisuudessan on:  skriptiajurissa tiedostojen nimissä saa olla myös: + { ; "  = ? ~ ( ) < > & * | $   koetellakseni skriptiajurin rajoja.
Koodia: [Valitse]
#!/bin/bash
function tehdään_mitä_määrätään () {
$@
}

tehdään_mitä_määrätään ls
read -p "paina return saadaksesi seuraavan tulosteen"
tehdään_mitä_määrätään ls -l
read -p "paina return saadaksesi seuraavan tulosteen"
tehdään_mitä_määrätään sudo blkid | awk '{print $1}' | tr -d : | sed 's,/dev/,,g'  # tulosta kovalevyn tunnetut osiot
**
- skriptiajurin desktop-käynnistin kuoli. Menin päätteseen ja annoin käskyn:

ln -sv "/home/petteri/OMATSKRIPTIT/Skriptiajuri" "/home/petteri/Työpöytä/AjaSkriptiajuri"

ja se loi työpöydälle linkin skriptiajuriin. Samalla konstilla voi luoda käynnistimen milletahansa skriptille. Eihän se hyvä ole, mutta parempi kuin ei mitään
- tämä edellyttää, että avataa nautilus näpäyttämällä pystypalkista tiedostot ja sieltä muokkaa - asetukset - toiminta - täppä kohtaan "kysy joka kerta"
**
- skriptiajuri toimii tällähetkellä UEFI/WereWolf:illa.
**
skriptiajurin hakukoneisiin olen aina haikaillut jotakin joka näyttäisi valitun tiedoston kaikki rivit ja hakutermi olisi esimerkiksi punainen muun tekstin ollessa musta. Kyllähän tuonkin ominaisuuden saa kikkailtua editoreihin, mutta olen halunnut keinoa jossa ei joudu tekemään monia asetuksia vaan kaikki toimii heti alkuunsa. Löytyihän se konsti lopulta:
Koodia: [Valitse]
grep --color -E "haettava regex|$" tiedosto ; read
- kun tekstiä näytetään saa se rauhassa olla suurempi kuin mitä näyttöön mahtuu, sillä tekstiä voi selailla esimerkiksi rullahiiren rullalla ja leikata "leikepöydälle" haluamansa ja lopettaa toiminta painamalla enter.
**
BASH:iakin kehitetään kokoajan. Eikä kehittäminen aina mene ihan nappiin ja toimivat skriptit alkavat joskus temppuilla. Nyt viimeksi käskylle: eval tehtiin jotakin ja skriptiajurista lakkasivat hakukoneet toimimasta. Ei tämä ensimmäinen tapaus ollut, mutta BASH:issa minkä toiminnon hyvänsä voi tehdä miljoonalla tavalla ja eikun uutta koodia - tai itseasiassa koodi supistui. Pahinta onkin se että yrittää itsepäisesti korjata toivotonta koodia eikä sensijaan tee uutta.
**
Skriptiajuri lakkasi toimimasta kun Wily päivitti itsensä: syyksi paljastui että "tput setf [värikoodin numero]" ei enää aseta värejä. Varmaakin joku tulevista päivityksistä korjaa sen, mutta nyt värit asetetaan koodilla: tput  setaf [värikoodin numero]
- siitä tämä BASH on kiva että voi tehdä mitätahansa  lukemattomilla eritavoilla; esimerkiksi tämän ongelman voi kiertää siirtymällä käyttämään valitun merkinnässäi inverse-videota joka on inhottavan näköistä mutta toimintavarmaa.
**
Kun tekee skriptin joka mielestäsi toimii niinkuin itse tahtoo kannattaa tarkistaa skriptistä siinä määriteltyjen muuttujien arvot ja mikäli muuttuja on matriisi niin sen jokaisen alkion arvo ja osoite. Koska tämän ominaisuuden käyttäminen yksinään on vaivalloista niin se kannattaa koodata skriptiajuriin kiinteästi. Silloin kun skriptiajurilla tekee skriptiä saa listauksen tehtävän skriptin kaikista silläkohtaa määritellyistä muuttujista kirjoittamalla skritiajurissa ajettavan skriptin koodiin käsky: Xref. Se kutsuu funktiota Xref:
Koodia: [Valitse]
#!/bin/bash 
# petteriIII 23.10.2015
# Xref-ohjelma tulostaa muuttujien arvot mikäli niiden nimessä on ainakin yksi pieni kirjain. tai kun niiden nimi on pelkästään yksi suuri kirjain jonka perässä voi olla yksi numero.
# echo -e "funktiot paikasta:"${0%/OMATSKRIPTIT*}"/OMATSKRIPTIT/FUNKTIOKIRJASTO/Xref_funktiot liitetään koodiin"

function Xref () {
function TulostaMuuttuja () {
[[ $(eval echo \$$1) ]] && echo -n $1':n arvo: ' && eval echo \$$1 || echo $1" on määrittelemätön"
}

function TulostaMatriisi () {
[[ $(eval echo \${$1[*]}) ]] && {
echo -n $1':n arvot    : '; eval echo \${$1[*]}   # arvojen väliin tulostuu välilyönti
echo -n $1':n osoitteet: '; eval echo \${!$1[*]}  # osoitteiden väliin tulostuu välilyönti.
}; echo ;}

function TestaaMuuttuja () {
[[ $(eval echo \${!$1[*]} | cut -sd' ' -f 2) ]] && TulostaMatriisi $1 && return # Matriisi voidaan tulostaa muuttujana jos siinä ei ole vähintään kahta jäsentä.
TulostaMuuttuja $1
echo
}

# echo -e "Xrefiä on kutsuttu skriptistä:"${0}".   Kutsu tehtiin riviltä:"${BASH_LINENO[0]}"\n\n"
muuttujalista=$(compgen -v | grep [[:lower:]] | grep -v ^_) # compgen -v:n muodostamasta muuttujalistasta poistetaan "ei halutut"
muuttujalista=$muuttujalista" "$(compgen -v | grep ^[A-Z]\[0-9]*$ | grep -v ^_) # lisätään listaan muuttujat joiden ensimmäinen kirjain on iso mutta senjälkeen ei mitään tai vain numeroita
for muuttuja in $muuttujalista; do TestaaMuuttuja $muuttuja; done
#apu=$(cat "${0}" | grep function ); [[ $apu > 0 ]] && echo "listaus skriptin funktioista:" &&  echo -e ' '"${apu[@]/%/\n}" 
}
**
Viimeaikaisia tekosia on zombien poisto. Kehittäminen on pikkuisen vaarallista puuhaa koska tiedostonimissä sallitaan * . Siis unohdapa käskyistä lainausmerkit niin kaikki poistuu.   
**
Sainpa kehitettyä yksirivisen skriptin joka laskee tiedostosta tagien välisten merkkiryhmien pituudet. Tämmöisen merkityshän on sinällään melkein olematon, mutta
on osoittautunut että tämmöisiin ongelmiin löytyy poikkeuksetta tällaisia nopeita skriptejä: nopeutta tulee lisää parikymmenkertaisesti ja koodikin supisuu melkein olemattomaksi.
Skriptiajurilla näitä tekee nopeasti. Ongelmana on ainoastaan ymmärtää mitä skriptin tulisi tehdä, osata jakaa se osiin ja osata pyytää skriptiajurilta apua.
Koodia: [Valitse]
grep -Po '(?<=<<).*(?=>>)' ~/tiedosto | awk '{split($0,a,"\n"); for (i = 1; i <= NF; i++) print length(a[i])}'
**
Kaikki vanhat tulosteet talletetaan myös ja niiden selaamiseen on tehty linkki. Pitänee pähkäillä milaisia haku-rutiineja niitä varten kannattaa tehdä.
Nimittäin mitään uutta ei saa lisätä niin että se muuttaisi vanhoja toimintoja tai edes haittaisi niitä.
« Viimeksi muokattu: 14.02.16 - klo:12.53 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #33 : 29.05.16 - klo:11.58 »
Siirsin foorumille SKRIPTIAJURISTA uuden version jossa Skriptiajurista on viimeisin versio ja Skriptiajurihiirelle toimii myös. En poista tuota edellistä versiota ennenkuin totean uuden version siirtyneen moitteetta.
- en ole tullut ajatelleeksikaan että tottakai jokainen haluaa säilyttää omat ARKISTO:nsa siirtyessään käyttämään uutta skriptiajuria. Täytyy jossain vaiheessa tehdä lisäosa siihen.

OMATSKRIPTIT on normaalisti kooltaan noin 100M. Mutta kun siitä poistetaan ARKISTO:t niin sen kooksi tulee noin noin 2M. Kun tämä tiivistetään nautiluksen *.tar.gz toiminteella tulee kooksi noin 600k joka mahtuu foorumille. Siirrettyäsi foorumilla olevan OMATSKRIPTIT.tar.gz-tiedoston omalle koneellesi siirrä se koti-kansioosi ja tupla-näpäytä sen kuvaketta ja muodostuvissa ikkunoissa näpäytä: pura.

ARKISTO:jen poistaminen ei juurikaan huononna Skriptiajurin toimintaa muuten kuin että se unohtaa kaiken mitä sillä on tehty - ja siirrettäessä ohjelma toisen henkilön käyttöön onkin vanhat jorinat syytä unohtaa. Mutta se haitta tästä on, että vaikka skriptiajuri toimiikin aivan kuten käyttöohjeissa kerrotaan niin se ei muista mitään vanhaa joten "oppimiskynnys" tulee korkeammaksi - tee muutamia skriptejä niin kyllä SKRIPTIAJURI alkaa hiljokseen toimia paremmin.
- alimman tason ARKISTO:ista osa on jäljellä, joten editoimalla SKRIPTIAJURIA itseään saat kuvan siitä millaiseksi editointi-ikkuna muodostuu.

Tehtyjä dokumentteja ei voi siirtää koska siirto veisi silloin liian paljon tilaa. Sensijaan jokainen huomio BASH:ista kannattaa aina tallettaa jonnekin, esimerkiksi OHJE-kansioon.Mutta minne sen talletaakin niin hakumoottorilla se löytyy.
- tee silti tekemistäsi skripteistä ainakin muutaman rivin dokumentti jossa esimerkiksi kerrot havaintojasi - tarvitset niitä muuten joskus itse.
**
Yhä useammin olen havainnut että arjen isohkotkin ongelmat ratkeavat usein yksirivisellä skriptillä - ja nämä yksiriviset skriptit eivät nopeudeltaankaan ole ihan surkeita. Mutta tuommoista yksirivistä on melko mahdoton tehdä heti alkaessaan skriptiä tehdä vaan kyllä kaikki skriptit ovat kehityksensä alussa moniriviä ja todella hitaita. Skriptiajuria voi käyttää koko kehityksen aikana - myös silloin kun skriptissä ei ole mukana edes riviä #!/bin/bash. Ja suoritusoikeuttahan skriptiajurin hallinnoimilla skripteillä ei ole koskaan.

Jokaisen skriptin voi kirjoittaa yhdelle riville, mutta en tarkoita tässä sellaisia. Vaan lyhyitä käskysarjoja joissa ei ole turhia hidasteita kuten esimerkiksi BASH:in omia looppeja.
**
Nopeus nousi taas vaikkei sillä nousulla tee enää mitään, skripti vain kiirehtii että pääsee odottamaan. Mutta onhan se teoriassa kivaa kun koodi samalla väheni.
**
Skriptiajurin paras ominaisuus on se ettei mitään tekemistään tarvitse harkita eikä mitään tarvitse muistaa, sillä pahin seuraus paniikki-kohelluksestakin on se että äskettäin tekemänsä joutuu tekemään osittain uudelleen. Ja käydä kurkkimassa edellisistä yrityksistä kuinka homma pitikään kirjoittaa sillä eihän BASH:in merkintätapoja muista. Kannattaa kuitenkin tallettaa työnsä vähänväliä ettei joutuisi kirjoittamaan pitkää litaniaa uudelleen.
- skriptaamisen merkittävin asia on puhua kaikista asioista niin pitkillä ja kuvaavilla nimillä että ne muistaa kuolemansa jälkeenkin. BASH itse puhuu arvoituksin mutta älä sinä puhu.
- nimissä kannattaa välttää erikoismerkkejä, ääkkösia ja välilyöntejä. Kuitenkin jos selvyys vaatii niin niitä täytyy käyttää mikäli BASH:in saa ne hyväksymään; vaikeuksia ei saa vältellä.
- tietysti skriptien tekeminen on nopeampaa jos muisti pelaa eikä koskaan kohella. Mutta jos ei muista edes perusasioita ja koheltaa vähänväliä tulee työskentelystä vain hirveän hidasta mutta eteneminen on kuitenkin varmaa.
« Viimeksi muokattu: 10.12.16 - klo:13.06 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #34 : 11.10.16 - klo:18.24 »
Skriptiajurista tuli uusi versio sillä edellisen version erikoistoiminnoissa oli paljon korjattavaa.
- vähän uuttakin, esimerkiksi skriptien tulosteet talletetaan nyt ja niitä voi käydä katsomassa painamalla nappulaa insert ja valitsemalla halutun kerran tuloste.

- skriptiajurin haku omalle koneelle:
1. näpäytä Ubuntu-foorumilla latauslinkkiä: OMATSKRIPTIT.tar.bz2 ja talleta. näpäytä latauslinkkiä Skriptiajuri (kopio).tar.bz2  ja talleta.
2. mene oman koneesi nautiluksella oman koneesi lataukset-kansioon (tai joskus lataus on mennyt kotikansioon)  ja siellä näpäytä: tiedostoa OMATSKRIPTIT.tar.bz2 ja avautuvasta pura ja avautuvasta taas pura ja lopeta. Näpäytä tiedostoa Skriptiajuri (kopio).tar.bz2 ja avautuvasta pura ja avautuvasta taas pura ja lopeta.
3. kotikansioosi on muodostunut OMATSKRIPTIT kansio ja käynnistin nimeltään Skriptiajuri. Siirrä käynnistin työpöytä-kansioon jos sellaista löytyy.
- kun tuplanäpäytät käynnistintä niin skriptiajuri käynnistyy.
- voit siirtää *.tar.bz2-kuvakkeet roskikseen.
- kun haluat päästä eroon skriptiajurista siirrä OMATSKRIPTIT ja käynnistin roskikseen; silloin skriptiajurin muistokin katoaa.
**
- taisinpa keksiä kuinka lyhyet viiveet saa mitattua tarkemmin skriptiajurissa: skriptin suoritusaika nimittäin riippuu siitä ajetaanko skripti omassa prosessissaan vai siinä mikä on jo auki. Sillä prosessin luominenhan kestää aina; milloin enemmän ja milloin vähemmän - joten luotaessa prosessi väärään aikaan skriptin mitattu toiminta-aika on liian suuri ja lisäksi aika vaihtelee kerrasta toiseen enemmän kuin ennen. Käytännössä korjaus aiheuttaa sen että "nollaskripti - siis kun skriptin käsky on kaksoispiste" kestää nykyään myös skriptiajurissa tosiaan 0 ms eikä 2-4ms. Skripti:
Koodia: [Valitse]
read -t 1
kestää myöskin oikean ajan eli 1.000 sekuntia.
**
- skriptiajuri on myös kirjailijan unelmatyökalu sillä kaikki tehdyt muutokset tallentuvat ja kun huomaa ettei muutos ollutkaan parannus niin vanhoista versioista on helppo palauttaa se mikä oli parempaa.
**
- skriptiajurin backup:ista ei tarvitse huolehtia sillä skriptiajuri kirjoittaa välittömästi kaikki muutoksensa USB-muistitikulle jos muistitikulla on kansio OMATSKRIPTIT. Muistitikun OMATSKRIPTIT kansio voi olla tyhjäkin jolloin sille kirjoitetaan koko kansio OMATSKRIPTIT.
- ominaisuuden saa toimimaan myös SSH:n yli.
- backupin tekeminen kestää skriptiajurin kannalta 2ms.
- USB-portissa voi olla muistitikku tai ei ja sillä voi olla kansio OMATSKRIPTIT tai ei ja se saa sijaita missä USB-portissa tahansa.  Backup toimii kaikille käyttäjille, eikä backupin toiminta ei riipu muistitikun nimestä,
  tiedostomuodosta eikä mistään muustakaan, vaan jopa FAT32 toimii samoinkuin NTFS mikäli ajuri löytyy.
- niin pientä muistitikkua ei olekaan ettei se riittäisi, eikä sillä ole väliä minkätyypin USB se on. Siis on mahdollista käyttää monimutkaistakin backup-menetelmää usealle muistitikulle.
- muistitikulla olevasta OMATSKRIPTIT-kansiosta ei koskaan poisteta mitään vaan ainoastaan lisätään. Tällätavoin menetellen siellä on enemmän myös roskaa, mutta toisaalta sellaista vikaa ei voi tulla että 
  jotain katoaa edes melkoisen hölmöilyn seurauksena. Muistitikulla olevan  OMATSKRIPTIT-kansion koon kasvaminen ei aiheuta ongelmia.
**
- työskentelyä arkistossa helpotettu merkitsemällä mitkä koodeista ovat käännöskelpoisia. Muutos näkyy myös skriptejä tehdessä.
**
BASH:illa voi tehdä koodin mihintahansa tehtävään mutta on turhaa hakea kirjoista mitenkä monimutkaisemmat hommat tehdään. Vihjeitä suoritustapaan kerätään sieltätäältä kunnes jossain vaiheessa saa mielikuvan kuinka asioiden täytynee olla. Mutta jos tekee skriptinsä ilman kehitysympäristöä on mahdotonta kokeilla onko mielikuva oikea, sillä kokeilemisen aikana asiasta valmistuu lukemattomia yritelmiä ja usein kehittäminen johtaa pitkiin umpikujiin joista pitää perääntyä sinne jossa tapahtui jotain oikeinkin. Mutta koska usein välissä on useampia pitkiä umpikujia ja aikaakin on kulunut viikkotolkkua niin et enää muista edes sitä  missä se "jotenkin toimiva" on ja on vaara että se alkuperäinen hento aavistus katoaa.

Skriptiajuri tallettaa kaikki koodit, mutta mikäli tekee paljon skriptejä niin etsiessään vanhoista koodeista mikä on se oikea kuluu aikaa tolkuttumasti sillä on vaikea etsiä sellaista jota ei pysty tarkasti kuvailemaan. Mutta vaikka koodia ei muistakaan niin sen muistaa mitä se tulosti - muistaa ainakin suurinpiirtein ja jokatapauksessa sehän kertoo jo paljon että koodi ylipäätään tulosti jotakin. Koska skriptiajuri tallettaa myös kaikki tulosteet ja kun selaa vanhoja tulosteita niin voi palauttaa koodin joka on tulosteen tehnyt.
**
Skriptiajurin kaikkia viestejä (siis myös sovellusohjelmien kirjoittamaa) voi lukea avaamalla vasemman laidan pystypalkista sen pääte ja rullahiiren rullalla saa tapahtumia seurattua olipa niitä kuinka paljon vaan.
- jos skripti romahtaa niin se ei juuri koskaan vie skriptiajuria eikä päätettä mennessään joten päätteestä näkee mitkä tapahtumat skriptin romahtamisen aiheuttivat.
- seuraamisen jälkeen saa vasemman puolen pystypalkista palattua sinne mistä lähdettiin.
- tai nautiluksella voi tiedostojen sisällön muuttumista  tarkkalla reaaliaikaisesti.
**
Aloinpa taas kokeilla sed:illä ja awk:illa ja esimerkiksi tämmöistä tuli esimerkkejä soveltaaen; ei näitä kokeilla tarvinnut sillä ne toimi heti:
Koodia: [Valitse]
sed "2s/$/ $(sed -n '7p' file1)/" file2  # selitys: tulosta file2 lisäten sen rivin 2 perään file1:n rivi 7
awk '{ if ($3&&/höh/) print $3 }' file   # selitys: tulosta kenttä 3 file:n riviltä 3 jos rivillä 3 on sana jossain sana höh

ja kun nämä kaksi naitetaan saadaan:
sed "2s/$/ $(awk '{ if ($3&&/höh/)print $3 }' file1)/" file2 # selitys: tulosta file2 lisäten sen rivin 2 perään file1:stä rivin 2 kenttä 3 mikäli file1:n rivillä 2 on jossain sana höh
- /$/ on: lisää perään ja /^/ on: lisää alkuun; myös välilyönnin paikkaa voi vaihtaa tai jättää pois. Ja kaikkia "numeroita" voi muuttaa. Tai lisääminen voidaan muuttaa korvaamiseksi kirjoittamalla /$/ paikalle esimerkiksi: /[[:alpha:]]/
- sekä sed että awk ovat skripti-kielinä pätevämpiä kuin BASH. Tässäesitetyt ovat yksirivisiä sed ja awk skriptejä, mutta on niitä monirivisiäkin. Kummmallakin on vaikea saada aikaiseksi toimivia skriptejä, mutta oikealla opastuksella melkein mihin käyttöön tahansa voisi tehdä nopeastitoimivan skriptin liikoja ponnistelematta. Joku semmoisen avustamana kuin skriptiajuri.
**
Ainakin minut saa raivoon mikäli jokin tekemäni katoaa ja sen joutuu "keksimään" uudestaan - vaikka uusi viritelmä olisi sangen todennäköisesti parempi eikä sen tekemiseenkään menisi kovin pitkää aikaa. Mutta otsasuonet kyllä olisivat haljenneet ja sen kadonneen etsimiseen  kulunut kohtuuton aika. Luulin skriptiajurin automaattisen backupin tehneen katoamisista mahdottomuuden ja niinhän se on tehnytkin. Vaan pahimmat katoamiset ovatkin sellaisia että koko skriptiajuri korvautuu jollakin skriptiajurin vanhalla versiolla esimerkiksi asennettaessa Ubuntu uudestaan ja kun kopioidaan sinne skriptiajuri jota luullaan viimeiseksi. Tällöin automaattinen backup backup:paa muistitikunkin muitakin skriptejä siihen kuntoon ettei viimeistä versiota osaa etsiä oikeasta paikasta elikä muistitikun arkistosta.
- jos automaati-backuppia ei halua käyttää niin riittää kun millään koneessa kiinniolevalla muistitikulla ei ole kansiota OMATSKRIPTIT. Mutta ei sillä kannata päätään vaivata sillä ei se tuhoa mitään, lisää vaan.

Jotta skriptiajurikaan ei enää voisi korvautua vanhalla versiolla niin ihan skriptiajurin alussa tarkistetaan ovatko kovalevyn tiedot vanhempia kuin muistitikulla - ja jos on niin kehoitetaan ihan ensiksi kopioimaan OMATSKRIPTIT- kansio muistitikulta.  Koska kyseessä on varautuminen todella harvinaiseen tilanteeseen niin tarkistus ei saa kestää kuin muutaman millisekunnin. Tämän toteuttaa esimerkiksi:
Koodia: [Valitse]
function varmista_että_kovalevyn_OMATSKRIPTIT_on_uudempi_kuin_muistitikulla_oleva () {Kone liittää USB-muistitikut /media-kansioon. Liitospiste muodostetaan kun USB-porttiin laitetaan muistitikku ensimmäisen kerran jonka jälkeen sen muodostama kansio ei poistu eikä sen omistaja enää vaihdu. Siis kyse on minkälaisen tikun laitat USB-porttiin ensimmäisellä kerralla - liitoskansio saattaa siis olla juuren omistuksessa vaikka se onkin käyttäjän nimellä. Tästä ei välttämättä ole haittaa mutta sotkuja se voi aiheuttaa.

Kansio /media on tarkoitettu liitoskansioksi esimerkiksi USB-muistitikuile ja sen pitäisi olla heti boottaamisen jälkeen tyhjä. Kuitenkin kansio on normaali kansio jossa voi olla tiedostojakin ja joskus kone nyrjähtää sellaisella tavalla että liitetty kansio siirtyy fyysisesti /media-kansion sisällöksi. Ja tällöin automaatti-backup:in päiväys menisi sekaisin sillä bacup toimisi vaikka muistitikkua ei olisikaan - kyllä se silti muistitikunkin päivittää jo se löytyy.
Kone tietää koska kansiossa /media on normaalejakin tiedostoja: käskyllä ls tulostuvat kaikki mitä siellä on ja käskyllä mount tulostuvat vain liitetyt, joten jos listattuja on enemmän kuin liitettyjä niin kansiossa on silloin normaalejakin tiedostoja.
kovalevynaika=$(stat /home/$USER/OMATSKRIPTIT --printf="%Y\n")      # aika sekunneissa Linuxin luomisesta 1.1.1970
muistitikunaika=$(stat /media/$USER/*/OMATSKRIPTIT --printf="%Y\n") # tuo * käy läpi kaikkien USB-porttien muistitikut jotta löytyisi se jolla on OMATSKRIPTIT-kansio.
(( $kovalevynaika < $muistitikunaika )) && echo -e "kovalevyn OMATSKRIPTIT on vanhempi kuin muistitikulla oleva, kovalevyllä se on:\n"$(date -d@$kovalevynaika)"   ja muistitikulla:\n"$( date -d@$muistitikunaika)"  Kannataisi ehkä kopioida muistitikun OMATSKRIPTIT-kansio kovalevylle." && read && exit;}
Mutta tämä ei ihan riitä, vaan sen bacup-rutiinin perään täytyy kirtjoitaa käsky: "touch ~/OMATSKRIPTIT" elikä kirjoittaa kovalevyn OMATSKRIPTIT-kansion viimeksi muutosajaksi nykyhetki.

Automaattinen backup aiheuttaa muuten sen että kun päivitettään skriptiajuri niin aikaisemmin sillä tehdyt skriptit ja kaikki arkistot löytyvät edelleen muistitikun OMATSKRIPTIT-kansiosta joten ne saa kaikki palautettua antamalla käskyn:
Koodia: [Valitse]
for n in $(ls /media/$USER); do [[ -d /media/$USER/$n/OMATSKRIPTIT ]] && rsync -au  /media/$USER/$n/OMATSKRIPTIT ~; done
**
Kovalevyllä olevia skriptejä voi ajaa silloinkin kun on bootannut muistitikulta:
- boottaa muistitikulta.
- mene nautilukseen.
- yläpalkkiin tulee: files   files. Näpäytä hiiren oikealla oikeanpuoleista "files" ja avautuvasta alasvetovalikosta valitse "Preferences" ja sieltä "Behaviour" ja siirrä täppä valintaan: ask what to do.  Sulje tämä ikkuna.
- nautiluksella navigoi ajettavan skriptin kansioon ja näpäytä skriptiä ja avautuvasta valikosta näpäytä "run in the terminal". ( Muuten navigointi alkaa näpäyttämällä: Other locations)

Myös kovalevyllä olevaa skriptiajuria voi ajaa kun on bootannut muistitikulta.  Se ei kuitenkaan toimi noinvain sillä:
Ajettaessa skriptiajuria Live-Ubuntulla muodostaa Live-Ubuntu liitospisteen sille medialle jolla skriptiajuri on ja tähän liitospisteeseen täytyy viitata kun skriptiajuri tekee jonkun levy-operaation. Lisäksi koska skriptiajurista saattaa olla kopioita monessakin paikassa  yhtaikaa niin skriptiajurin kanta (joka on skriptiajurin koti-kansio) muodostetaan seuraavasti:
- mikäli omassa kotikansiossa on skriptiajuri niin käytetään sitä.
- ellei  omassa kotikansiossa ole skriptiajuria niin käytetään sitä skriptiajuria jonka OMATSKRIPTIT-kansio on viimeiseksi päivitetty. Koodina tämä on:
Koodia: [Valitse]
kanta=''; kanta=$([[ -d /home/$USER/OMATSKRIPTIT ]] && echo "/home/$USER" || apu=("$(find  /media -maxdepth 4  | grep -w OMATSKRIPTIT | grep -v OMATSKRIPTIT/ | grep -v \(*\) )") &&\
 for n in ${apu[*]}; do echo $(stat -t $n | awk '{print $13" "$1}'); done | sort -k1 -n | tail -1 | awk '{print $2}' | sed 's/\/OMATSKRIPTIT//')
- mutta tiedostojen ja kansioiden luku-, kirjoitus- ja poisto-oikeudet ovat erilaiset kun käyttäjä on joku ihminen tai live-Ubuntu ja tämä aiheuttaa joskus vaikeuksia ellei jyrää omistusoikeuksia. Käytännössä tämä näkyy siina että live-Ubuntua käytettäessä jotkut tiedostot ovat lukittuja. Siirry tällöin "sudo nautilukseen" ja laita kaikki omistusoikeudet avoimiksi kaikille. Mutta toisaalta Live-Ubuntulla on kokoajan päälläoleva sudo-oikeus elikä se ei koskaan kysy salasanaa - tiedoksi muuten, että joskus erittäin harvoin kysyy, ja silloin se on: ubuntu.
**
Skriptiajuri tarkastelee nyt omaa toimintaansa ja kirjoittaa alussa tapahtumia botanneen levyn tiedostoon: /tmp/skriptiajuri , jotta skriptiajurin kaatuessa syytä olisi helpompi etsiä.
Koska kirjastoja kehitetään jatkuvasti saattaa niiden koodiin lipsahtaa virhe joten niiden koodi täytyy todeta toimivaksi niiden lataamisen yhteydessä ja mikäli kirjasto ei toimi tästä ilmoitetaan ja toiminta keskeytyy.
- muuten näiden tarkastelujen tuloksia voi selata hiiren rullalla kun ollaan pääte-tilassa (silloi siis kun näytetään tiedostolistausta). Kyseessä on siis dmesq jota ei tarvitse kutsua.
**
Live-Ubuntulla ei nykyään voi olla omaa talletustilaa johon voisi sijoittaa OMATSKRIPTIT-kansion ja ajaa skriptiajuria sieltä. Kuitenkin kun on bootattu Live-Ubuntulla voi skriptiajuria ajaa toiselta muistitikulta joten kiintolevyllä ei välttämättä tarvitse olla OMATSKRIPTIT-kansiota jotta skriptiajuria voisi ajaa. Tai skriptiajurin kautta MidnightCommanderia.
**
Meni koko päivä backup-toiminnan parantamiseen. Katselin illalla päivän saavutuksia ja taas kertaalleen havaitsin ne mitättömiksi. Mutta noinhan se on aina: kun katselee valmista työtä niin ihmettelee kuka idiootti voi edes kuvitella että mikään muu onnistuisi. Pari seikkaa tuli esiin:
- kone liittää USB-muistitikut /media-kansioon. Liitospiste muodostetaan kun USB-porttiin laitetaan muistitikku ensimmäisen kerran jonka jälkeen sen muodostama kansio ei poistu eikä sen omistaja enää vaihdu. Siis kyse on minkälaisen tikun laitat USB-porttiin ensimmäisellä kerralla - liitoskansio saattaa siis olla juuren omistuksessa vaikka se onkin käyttäjän nimellä. Tästä ei välttämättä ole haittaa mutta sotkuja se voi aiheuttaa.
- kansio /media on tarkoitettu liitoskansioksi esimerkiksi USB-muistitikuile ja sen pitäisi olla heti boottaamisen jälkeen tyhjä. Kuitenkin kansio on normaali kansio jossa voi olla tiedostojakin ja joskus kone nyrjähtää sellaisella tavalla että liitetty kansio siirtyy fyysisesti /media-kansion sisällöksi. Ja tällöin automaatti-backup:in päiväys menee helposti sekaisin sillä bacup toimisi vaikka muistitikkua ei olisikaan - kyllä se silti muistitikunkin päivittää jo se löytyy.
Kone tietää koska kansiossa /media on normaalejakin tiedostoja: käskyllä ls tulostuvat kaikki mitä siellä on ja käskyllä mount tulostuvat vain liitetyt, joten jos listattuja on enemmän kuin liitettyjä niin kansiossa on silloin normaalejakin tiedostoja.
**
Kaikkien skriptien toiminnassa on yksi yhteinen piirre: vaikka yleensä onkin yhdentekevää millaisessa koneessa skripti toimii niin usein olisi mukavaa saada se helposti selville - ja joillain harvoilla skripteillä se on "pakko". Skriptiajuri hoitaa  ottaa aina selville koneen piirteitä mutta tulostaa ne sellaiseen paikkaan joka normaalisti on näkymättömissä. Esimerkiksi: laita skriptiajuri toimimaan ja heti alkuun pyöritä hiiren rullaa. Näkyviin tulee tietoja koneesta. Näyttö muuttuu normaaliksi heti kun teet jotakin muuta, esimerkiksi painat nuoli-näppäintä.
- skriptiajurin näyttöä voi aina selailla oltaessa pääte-tilassa. Siellä on muunmuassa kaikki ne viestit mitä skriptisi on tehnyt: enää ei tarvitse pähkäillä että mikä viesti siellä näytössä vilahti vaan voi mennä katsomaan. Näitä viestejä voi olla kymmeniä sivuja.
**
Kun skriptiajuria käytetään skriptien tekemiseen niin koska tekemisen muut piirteet ovat hallussa jää skriptien tekemisen tehokkuus eniten riippumaan siitä kuinka tehokasta on komentorivin käyttö. Ja komentorivin käyttämisen nopeus riippuu eniten siitä kuinka osaa käyttää historiaa - mutta bash:in omasta historiasta haku elikä käsky ctrl-r on käyttökelvoton. 
- selvitys: komentoriviä täytyy käyttää että saataisiin jokainen käskyrivi testattua yksikseen sillä rivien testaaminen valmiissa skriptissä on tosihidasta - valitettavasti niin on joskus pakko tehdä.
 
Skriptiajurissa on toiminto: etsi tiedostosta: ~/.bash_history jolloin historiatiedot esitetään kerran ja sitä samasta hakutuloksesta haetaan kunnes ollaan tyytyväisiä. Historiatiedot pysyvät kokoajan samassa järjestyksessä, eikä vähänväliä suoriteta samaa hakua uudestaan joka lisäksi sekoittaa järjestyksen. Lisäksi haku käyttää kunnon hakumoottoria kuten esimerkiksi grep:iä regex:än tukemana, haku voi alkaa etsittävän alusta, keskeltä tai lopusta, haku ei aina onnistu ensimmäisellä haulla jolloin edellisen haun hakutermin voi seuraavassa haussa palauttaa skriptiajurin historiasta ja editoida sitä ...
**
Tällätavoin tutkittavia tiedostoja on kymmeniä ja mikäli niille kaikille tekisi valintaan oman kohdan tekisi se valinnasta sotkuisen, eikä isosta joukosta ei ole mukava valita jos samassa paikassa tehdään valintoja toisentyyppisillekin asioille. Kysymys on siitä, että valinnoissa on aina hyvä olla joku arvo joka valitaan mikäli painetaan enter edes lukematta valintoja. Tämä oletusarvonhan voi muuttaa joka valinnassa siihen mikä valitaan. Nopeaa ja tosiaan toimii mikäli valintapaikassa on ainoastaan samankaltaisia asioita sillä käytännössä sama asia valitaan montakertaa uudelleen ennenkuin homma on selvä.

Täytyi siis tehdä geneerinen "mistä tiedostosta haluat valita" . Näin alkuunsa valintoja on vain muutama, mutta niitä on helppo lisätä käynnin aikana rajattomasti - ja siis tällä valinnalla on oma oletusarvo
Siis täytyi tehdä rakenteet valintalistan levyltä lukemiseksi, valintalistan dynaamisesta muuttamisesta ja muutetun valintalistan tallettamisesta levylle. Myös "oletusvalittavan" lukemisestalevyltä, muuttamisesta  ja tallettamisesta levylle tulee huolehtia. 
**
yhtaikaa voi olla käynnissä monta skriptiajuria: yksi näyttää OHJEITA, toinen on kokoajan erikoistoiminnoissa, kolmas skriptinteossa ja neljäs dokumenttia väsäämässä. Kuitenkin homma edellyttää liikaa näpräämistä jotta itsekään innostuisin - sen toimimisen olen tarkistanut jo ja käytössäkin se saattaisi olla ihan käyttökelpoinen menetelmä kun vaan viitsisi harjoitella. Mutta kunnon koneet ja 4k-näytöt muuttavat koko asetelman, sillä jokainen skriptiajuri olisi yhtaikaa näkyvissä ja niiden välillä voisi kopioida.



« Viimeksi muokattu: 10.12.16 - klo:06.01 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #35 : 10.12.16 - klo:12.30 »
Skriptiajuri sai lisää käynnistysviestejä. Nyt niissä on muunmuassa:

Skriptiajuri käynnistyy. Tässä koneessa on BASH:in versio: 4.4.5(1)-release.  Versio 4.0 toimii jotenkin ja ylemmät versiot kunnolla
tämän skriptiajuri-version päiväys on (vvvv-kk-pp): 2016-12-20
- ja lukemattomia korjauksia, toiminnan järkeistämistä, ja roskaakin on poistettu runsaasti minkä takia koko laski paljon  ... ja esimerkiksi siirrot tapahtuvat nykyään toisin jne.

- käynnistysviestit saa näkyviin kun skriptiajurin käynnistyttyä rullaa näyttöä hiiren rullalla tai oikean reunan hissillä. Versiopäiväyksen näkee myös painamalla nappia f3.
- foorumilla on myös kerrottu mikä on siellä olevan skriptiajurin versiopäiväys.
**
Skriptiä tehdessä täytyy käyttää versiohallintaa. Jokaisen version tulosteet täytyy säilyttää ja niiden hoitoon täytyy olla tulosteidenhallinta. Ja tulosteidenhallinnastta täytyy olla linkki versiohallintaan.
- mutta mitä ominaisuuksia lisätäänkin niin perus-käyttöön se ei saa vaikuttaa huonontavasti. Mitään ei saa muuttaa.

Tulosteiden säilyttäminen ei yleensä vaadi paljoakaan kovalevytilaa koska normaalisti tulosteiden koko ei ole suuri eikä tilaa kulu paljoakaan vaikka tulosteita olisi tallessa lukemattomia. Mutta joskus skripti tulostaa gigabittejä niin monta etteivät ne mahdu mihinkään ja ennenkaikkea tallettaminen kestää iäisyyksiä. Mutta automaattinen tulosteiden poisto ei toimi, käsipelin se täytyy tehdä. Tulosteiden hallinnassakin sen voi tehdä esimerkiksi niin että kun skriptiä kehittää kokoajan ei poista mitään, mutta kun skripti toimii hyvin niin poistaa sen tulosteista melkein kaikki.

Laitoin foorumille version: 2016-12-20 .
**
Tein estot ettei mahdottomia valintoja edes näytetä evätkä ne myöskään toimi. Huomioipa että kansion dokumentointi on oikeastaan mielekästä; dokumentissa voidaan kertoa tuhannella rivillä mitä kaikkea kansiosta löytyy.
**
Sain lopultakin ratkaistua kuinka tiedostot ja kansiot siirretään - se on melkoinen ongelma silloin kun täytyy siirtää kymmeniä tiedostoja ja kansioita samallakertaa mikäli halutaan arkistojen siirtyvän myös.
- ja normaali ilmiö: kun ratkaisu on valmis on se niin selväpiirteinen että muut keinot tuntuvat ihan idioottimaisilta.
**
Skriptiajuri toimii silloinkin kun ei saa bootattua graafiseen tilaan. Mutta ilmeisesti Gedit ei toimi - MidnightCommanderia voi kylläkin ajaa silloinkin. Ilmeisesti opiskelun paikka.
**
Pari viikkoa olen nyt tehnyt skriptiä joka osoittaa taas kertaalleen että bash esitetään paljon huonompana kuin se todellisuudessa on. Tehtävä on iso, tällähetkellä skriptistä on jo 600 versiota ja se toimiikin jo kuin unelma. Versioiden suuri määrä johtuu siitä että skriptiajuri on hyvä.

Esimerkiksi kun aamuisin herään ja boottaan koneeni niin skripti ilmestyy ruudulle heti kun skriptiajurin käynnistää. Ja kun muuttaa skriptiä tarkoituksella että taas paranisi niin yleensä jokin menee pieleen. Jolloin se vanha versio palautetaan. Palautuksia on tullut tehtyä jo 500 sillä palauttaminen on nopeaa.

Tai kun työnalla on lukemattomia muitakin skriptejä niin siirryäni editoimaan jotakuta  voinkin idean iskiessä keskenkaiken palata nopeasti tuohon isoon. Tai mihintahansa viimeaikoina editoituun skriptiin pääsee kahden napin painalluksella.
**
Skriptiajuri on tehnyt vallankumouksen sellaisten skriptien tekemisessä jotka maailman parhaat virtuoosit sanovat mahdottomiksi. Mutta täydellistä skriptiä ei kannata yrittää tehdä heti vaan kehityksen aikana valmistuu tuhat versioita ja koe-ajoja niille useampi tuhat. Versioita on alkuaikoina kyennyt tekemään päivässä kymmenen, nyt viisisataa.

Esimerkiksi monessa skriptissä on kehityksensä aikana ollut monta vanhojen uskomusten mukaan mahdotonta ominaisuutta. Jokaisen ominaisuuden kehittämisen aikana on välillä tehnyt kymmeniä versioita kunnes on tajunnut että jossain vaiheessa on mennyt vikaan. Milloin tämä vikaan meneminen alkoi ja mihin versioon tulisi pakittaa ja alkaa siitä lähtien uudestaan? Skriptiajurikaan ei osaa kertoa sitä, mutta koska sillä on kaikki vanha muistissaan niin voi kokeilla koska toimi sentään jotenkin.

- semmoista asiaa ei tunnu olevankaan kuin "ei voi toimia" vaan kaikki onnistuu jotenkin. Ja nimenomaan tulee kokoajan muistaa että bash on erilainen kuin muut kielet.
- esimerkiksi yleisesti käytetään bash:iin kiinteästi kuuluvista käskyistä alle yhtä prosenttia. Tämä johtaa siihen että 99%:iin käskyistä löytyy vain man-sivu, mutta niistähän ei saa selvää ennenkuin asia on muutenkin selvä sillä niissä on harvoin esimerkkejä. Eikä niitä esimerkkejä maailmaltakaan löydä. Eikä edes käskyjen nimiä löydä helposti; tai pikemminkin kun löytää niin löytää samanaikaisesti niin monta että masentuu. Ja myös nämä 99% ovat virtuoosien tekemiä ohjelmia joita ei käytetä koska niiden toiminta on vaikeasti tajuttavissa - nähtävästi virtuooseillekin.

***
Skriptatessa koipeani ei tajuttomasti pakota - ja sitäpaitsi nautin sadistisesti virtuoosien kurmuuttamisesta. Joten aamun ensimmäisenä työnäni avaan skriptiajurin ja skriptailen sillointällöin. Skriptiajuri on toiminut täysin moitteetta sen jälkeen kun se seitsemänvuotta sitten valmistui - edes BASH:in versioiden vaihtuminen ei ole vaikuttanut. Skriptiajuri on aikatavalla samanlainen kuin aikoinaankin - joten ei tuota mastodontin kokoista järkälettä kannata laittaa tänne foorumille - aikomuksena se kyllä on muttei tunnu onnistuvan - en osaa karsia oikein - eikä skriptiajuri ole edes virheillyt ja sehän kyllä pakottaisi päivitys-rumbaan.

Mutta yksi vika skriptiajurilla on: se muistaa liian hyvin ja sen seurauksena turpoaa nopeasti joten välillä täytyy karsia sitä väkisin. Kirjoitankin tänne foorumille merkittävimmät skripteistäni jotta voisin hakea niitä takaisin kun jotain käyttökelpoista tulee vahingossa karsittua - olenkin jo monia kertoja hakenut foorumilta takaisin jotakin josta olen tuhonnut oman versioni.

Mutta jokainen skripti jonka teen on skriptiajuri mielessä tehty - ja joukossa on runsaasti kummajaisia koska senjälkeenkään kun skripti on valmistunut ei pitkään aikaan voi tietää mikä skriptin merkitys myöhemmin tulee olemaan - ja kerryttäähän skriptiteko ainakin kokemuksia.

Teinkin täysin toisentyyppisen kummajais-skriptin kuin aikaisemmat ovat olleet - sen työnä on kääntää 'desimaaliset binääriluvut' kymmenjärjestelmään - siis kääntää luvut tyyppiä: 10110110.111101011 . En kuvittelekaan kenenkään koskaan käyttävän näin harvoin tarpeellisesta asiasta tehtyä skriptiä - ehkä sentään kokeilevan. Syy sen tekemiseen oli se että tuo käännös tuntuu olevan vaikea C-kielessäkin ja halusin kokeilla selviääkö BASH pienemmällä koodimäärällä - ja selvisihän se. Tosin tämän skriptin tarkkuus on aika vähäinen mutta onhan tämä epätarkka versio ainakin BASH-skriptiksi nopea.

- siis kyseessä on lukua: 111111111111111111111111111111111111111111111111111111111111111.11111111111111111111111111111111111111111111111111111111111  vähänumeroisempien binäärilukujen kääntäminen kymmendesimaalisiksi . Kokonaisosan kääntäminen kestää noin 50 mikrosekuntia ja mikäli desimaaliosaa ei ole niin se onkin skriptin nopeus. Mutta mikäli desimaaliosaa on niin kääntäminen kestää noin 0.5 millisekuntia. Kokonaisosan käännös on aina tarkka mutta jos desimaaleja yli 30 niin käännöksen muutama viimeinen numero saattaa alkaa höpertää ja käännökseen kuluva aika kasvaa lopulta noin 2:een millisekuntiin.  Käännettävällä ei juurikaan ole muotomääräyksiä - muotomääräysten poistamiseen upposi pari koodiriviä.
- bc on mukana vain koska se tarjoaa varmasti oikean tuloksen johon verrata tämän skriptin tulosta: bc:n tulos on tulosteessa ylempi rivi ja tämän skriptin tulos on alla. Jos nopeutta haluaa niin bc:n kutsu täytyy poistaa kummastakin paikasta - jos koodissa edes puhutaan bc:stä niin koodista tulee hidas.


function 2to10 () { # uusi huomattavasti paranneltu versio
number=$1
[[ ${1//[^.]/} ]] || { bc<<<"obase=10; ibase=2; $number"; echo $((2#$number)); return ;}
[[ ${number:0:1} = . ]] && number=0$number 
decimalpart=${number##*.}
integerpart=${number%%.*}
bc<<<"scale=18;obase=10; ibase=2; $1/1"  # scale otetaan bc:ssä huomioon vain kun kyseeessä on jakolasku ja yhdellä jakaminen ei muuta mitään.
echo -n $((2#$integerpart))
binarydecimals=1000000000000000000; for n in {1..63}; do (( ${decimalpart:$n-1:1} )) && binarydecimals=$(($binarydecimals+1000000000000000000/(2**$n))); done; echo .${binarydecimals:1} ;}

# esimerkkikutsu:
2to10 111111111111111111111111111111111111111111111111111111111111111.00000000000010000000000000000000000000000000000000000000111
     
- nuo pitkät nollasarjat desimaaliosan alusssa ja keskellä ovat vaikeita kääntää joten sellaisilla kannattaa testata.

***

Miksi teen näitä BASH skriptejäni? - sillä eihän niillä ole enää nykyään mitään arvoa eikä käyttöä. Mutta tässävaiheessa ei ole aikomuskaan tehdä mitään hyödyllistä - vaikka onhan se kerro18 etopeli. Vaan tarkoituksena on esittää kertomus: kauan sitten kaikilla skriptikielillä harrastettiin tällaisia leikkejä ja sääliteltiin BASH-parkaa kun se ei tämmöisiin kyennyt - ja tämä uskottelu oli yksi monista tekosyistä joilla BASH hiljokseen kammetiin pois skriptauskielten kuninkaan paikalta. Mutta tosiasiassa tällaiset skriptit olisivat toimineet jo silloin - niiden tekeminen olisi ollut silloin jopa helpompaa koska niiden nopea toiminnan mahdollistavat vanhat käskyt olivat skriptaajilla paremmin muistissa.

Muista virtuoosien *tahallisista* virheistä olen kirjoittanut jo aikaisemmin ja nyt on vuorossa matematiikka.

Mutta yhä vielä nuo samat virtuoosit tekevät 'advanced guideja' vaikka ovat toimillaan syösseet BASH:in turmioon. Paljon noissa 'advanced guideissa' tosin on asiaa ja ihan kunnolla esitettyinäkin, ei sitä kieltää voi. Oikeastaan vika on vain siinä että niiden pitäisi kertoa että esitetyt asiat ovat epätäydellisesti esitettyjä alkeita - sillä BASH on niin laaja etten usko että yksikään virtuoosi hallitsee siitä oleellista osaakaan - ei BASH siis oikeastaan ohjelmointiin ole tarkoitettukaan vaan vain haasteeksi jonka voi yrittää voittaa. Siihen en ota kantaa möhläsivätkö virtuoosit typeryyttään vai siksi etteivät pystyneet tunnustamaan etteivät hallitse omaa erikoisalaansa.

Olen aina ihmetellyt kuinka käyttäjät siirtyivät välittömästi pois BASH:ista kun muita kieliä alkoi tulla ja alkoivat tulisesti kannattaa ensin Perliä ja sitten Pythonia. Uskoivatko he virtuoosien valheita BASH:in kyvyttömyydestä? Mutta täytyy myöntää että BASH:in merkintätavat ja kammottava laajuus tekevät sen että vaatimattomankin skriptin tekemisessä on niin iso työ ettei se oikeastaan enää ohjelmointia ole - varsinkin kun usein toimitaan tavoilla jotka ovat rikollisluonteisia muissa kielissä. Lopuksi täytyy kyllä sanoa että koska BASH:ia on jo vuosikymmeniä kehitetty olemattoman vähän on se jäänyt kehityksen jalkoihin ihan täysin - tosin koska tämmöinen dementoitunut epä-matemaatikko saa aikaan tällaisia skriptejä niin kunnollinen matemaatikko saisi silti BASH:ista irti ihan ihmeitä.

Esimerkiksi jakolasku - se toimii nopeasti ja teoriassa sen tarkkuus on rajoittamaton, parisataa desimaalia irtoaa kevyesti. Tosin joskus se hölmöilee -jopa aika alussa - enkä minä epämatemaatikkona saa sitä korjattua. Enkä osaa poistaa sen jakajan 18-merkin rajaakaan - mahdollista se kuitenkin olisi - pitkällä jakolaskulla kenties?
« Viimeksi muokattu: 02.09.23 - klo:15.04 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #36 : 03.09.23 - klo:19.54 »
 Aloin suunnitella kuinka lasketaan kulman sinin arvo Taylorin sarjan mukaisesti. Taylorin sini-sarja on : sin x= x - x³/3! + x⁵/5! - X⁷/7!... ja siinä kulman arvo on radiaaneissa. Sikäli homma oli helppo että kaikki sen tarvitsemat funktiot on tehty jo - funktioiden koodia on paljon mutta itse skriptiä vähän. Ei merkitse mitään että kaikkikin tämän kaltaiset skriptit ovat hitaita ja kovin rajoittuneita - sillä kun ne saa toimimaan on se verraton voitto. Ja BASH:in kanssa on varmaa että mikään ei selviä helposti mutta kaikki selviää lopuksi.

Ja tälläkertaa tein ensiksi kunnon kuvauksen kuinka hommien pitäisi tapahtua enkä vain harakanvarpailla tupakkiaskin kanteen söherrettyä arvoituksellista hieroglyyfiä - eikä siinä vaiheessa mitään ollut tehtynä itse skriptistä.

- se mistä sini pitäisi laskea on x. Siis sen arvoa ei saa koskaan muuttaa eikä käyttää mihinkään muuhun eikä edes nimetä toisin. Ja siitä lasketun sinin merkintä on: sin_x
- laskun nopeus on noin 50ms
- arvot ovat muuten radiaaneissa. Yksi radiaani on noin 57 astetta.
- tarkkuutta rajoittavaksi tekijäksi tulee jakolasku - BASH:issakin on laskuihin pakko käyttää sen 18:sta merkkisille kokonaisluvuille tehtyä laskentamoottoria josta kyllä saa väsättyä nopean desimaalilaskimen mutta se 18:sta merkin rajoitus on jakajalla sittenkin. Lasku on tyyppiä: $((a/b)). Laskuissa tuo b on kertoma ja siinä ei siis saa olla numeroita enemmän kuin 18 - takanollat voi kuitenkin poistaa ja liittää tulokseen laskun jälkeen - niitä takanollia onkin 21-kertomassa neljä.
- mutta toisaalta kertoman laskenta on yksinkertainen tapahtuma eikä vaadi omaa funktiotaan.
- mitä sopisi odottaa tarkkuudeksi tulevan kahden radiaanin kohdalla: viimeinen korjaustermi on: .0000000001865792386 -> tarkkuus on noin kymmenen desimaalia
- korjaustermin merkin määritteleminen: (( $n==19 | $n==15 | $n==11 | $n==7 | $n==3 )) && kerroin=-1 || kerroin=1


***   funktiot kerro, jaa ja yhteenlasku*********************************************************************************************
Koodia: [Valitse]

function kerro18 () {
local apu apu1 apu2
tulosta=: # yhdessä paikassa päätetään tulostetaanko välituloksia. Vaihtoehdot:tulosta=echo ja tulosta=:
luku1=${1:0:17}; luku21=${2:0:17}
# [[ ${#1} -gt 18 || ${#2} -gt 18 ]] && echo laskettavissa liikaa numeroita && return
$tulosta "annetut numerot: "$luku1 $luku2
[[ ${1:0:1} = - || ${2:0:1} = - ]]  && merkki=- || merkki=''''
[[ ${1:0:1} = - && ${2:0:1} = - ]]  && merkki=''
apu1=${1//\-/}; apu2=${2//\-/}
desimaaliosa1=${1##*.};
desimaaliosa2=${2##*.};
[[ ! ${apu1//[^.]/} ]] && desimaaliosa1=''
[[ ${apu1//[^.]/} ]] && { luku1=${apu1:0:18}; kokonaisluku=0 ;} || { luku1=${apu1:0:18}"."; kokonaisluku=1 ;}
[[ ! ${apu2//[^.]/} ]] && desimaaliosa2=''
[[ ${apu2//[^.]/} ]] && { luku2=${apu2:0:18}; kokonaisluku=0 ;} || { luku2=${apu2:0:18}"."; kokonaisluku=$(( 1 & $kokonaisluku )) ;}
 desimaaleja=$((${#desimaaliosa1}+${#desimaaliosa2})); $tulosta desimaaliosa1:$desimaaliosa1"   desimaaliosa2:"$desimaaliosa2"   desimaaleja:"$desimaaleja
luku1=000000000000000000${luku1//./}
luku2=000000000000000000${luku2//./}
a=${luku1: -18:9}; b=${luku1: -9}
c=${luku2: -18:9}; d=${luku2: -9}; $tulosta $a' '$b; $tulosta $c' '$d
luku1=00000000000000000000000000000000000000$((10#$b*10#$d))
luku2=00000000000000000000000000000000000000$((10#$d*10#$a))"000000000"
luku3=00000000000000000000000000000000000000$((10#$c*10#$b))"000000000"
luku4=00000000000000000000000000000000000000$((10#$a*10#$c))"000000000000000000"
luku1=${luku1: -36} ; $tulosta $luku1
luku2=${luku2: -36} ; $tulosta $luku2
luku3=${luku3: -36} ; $tulosta $luku3
luku4=${luku4: -36} ; $tulosta $luku4; $tulosta
luku11=${luku1:0:18}
luku12=${luku1:18}; $tulosta a$luku11' 'b$luku12
luku21=${luku2:0:18}
luku22=${luku2:18}; $tulosta c$luku21' 'd$luku22
luku31=${luku3:0:18}
luku32=${luku3:18}; $tulosta a$luku31' 'b$luku32
luku41=${luku4:0:18}
luku42=${luku4:18}; $tulosta c$luku41' 'd$luku42;$tulosta
summa1=$((10#$luku12+10#$luku22+10#$luku32+10#$luku42)); $tulosta summa1:$summa1
summa1pituus=${#summa1}; ylivuoto=0; (( $summa1pituus >= 19 )) && ylivuoto=${summa1:0: -18} && summa1=${summa1:1}
summa1=000000000000000000$summa1; summa1=${summa1: -18} ;$tulosta ylivuoto:$ylivuoto' summa1:'$summa1
summa2=$((10#$luku11+10#$luku21+10#$luku31+10#$luku41+$ylivuoto)); $tulosta summa2:$summa2
# echo; echo tulos laskusta: $1 \* $2'  . Ylärivi on bc:stä ja alarivi tästä skriptistä:'
# bc<<<"scale=40; $1*$2"
(( $summa2 )) && : || summa2=000000000000000000
(( $kokonaisluku )) && tulos=${summa2/*(0)/}$summa1 || { apu=$summa2$summa1; tulos=${apu:0: -$desimaaleja}.${apu: -$desimaaleja} ;}
echo $merkki${tulos##+(0)} ;}

#---

function jaa () { (( ! $# )) && echo funktion ajokäsky on muotoa: jaa 1 2 . Siitä pitää tulla: .5000000000000000000000000000 && sleep 2 && return
local apu apu1 apu2
tulosta=: # yhdessä paikassa päätetään tulostetaanko välituloksia. Vaihtoehdot:tulosta=echo ja tulosta=:
# kun jakaja kasvaa yli 18 numerosta alkaa tulo epätarkentua kymmenenteen osaansa jokaista ylimääräistä numeroa kohti - jolloin desimaalipisteen jälkeen tulee yksi nolla lisää. Siten vielä 35 numeroinen jakaja antaa jonkinlaisen tuloksen. luku=${luku##+(0); lkm=${#luku}; [[ $lkm>18 ]] && { ekstranollia=printf "%${lkm-18))s" | tr " " 0; luku1=${luku1:0:17} ;}
 
[[ ${1//[^.]/} ]] && luku1=$1 || luku1=$1"."
[[ ${2//[^.]/} ]] && luku2=$2 || luku2=$2"."

desimaaliosa1=${luku1##*.}
desimaaliosa2=${luku2##*.}
kokonaisosa1=${luku1%%.*}
kokonaisosa2=${luku2%%.*}

#desimaaliosat yhtäpitkiksi:
(( ${#desimaaliosa2} >= ${#desimaaliosa1} )) &&
{ apu=$desimaaliosa1"00000000000000000000"; desimaaliosa1=${apu:0:${#desimaaliosa2}} ;} || { apu=$desimaaliosa2"00000000000000000000"; desimaaliosa2=${apu:0:${#desimaaliosa1}} ;}
$tulosta $kokonaisosa1$desimaaliosa1
$tulosta $kokonaisosa2$desimaaliosa2

#kokonaisosat yhtäpitkiksi:
(( ${#kokonaisosa2} >= ${#kokonaisosa1} )) &&
{ apu="00000000000000000000"$kokonaisosa1; kokonaisosa1=${apu: -${#kokonaisosa2}} ;} || { apu="00000000000000000000"$kokonaisosa2; kokonaisosa2=${apu: -${#kokonaisosa1}} ;}
luku1=$kokonaisosa1$desimaaliosa1;luku1=$((10#$luku1))
luku2=$kokonaisosa2$desimaaliosa2;luku2=$((10#$luku2))
$tulosta jaettava:$luku1"   "jakaja:$luku2

(($luku1 >= $luku2)) && { apu=$(($luku1/$luku2)); kokonaisiatulosteessa=${#apu}; nolliatulosteessa='' ;} || { apu=$(($luku2/$luku1)); apu=${apu//[1-9]/0}; nolliatulosteessa=${apu:1}; kokonaisiatulosteessa=0;}

$tulosta nolliatulosteessa:$nolliatulosteessa"   "kokonaisiatulosteessa:$kokonaisiatulosteessa   

# tähänasti on selvitetty desimaalipisteen paikkaa. Nyt aletaan laskea numeroita.
unset tulos # vain varmistus että kaikki on tuloksessa tämänjälkeen uutta
luku1=${luku1##+(0)}; luku1=${luku1%%+(0)} # poistetaan etu-ja takanollat sillä tästälähtien ne vain haittaavat.
luku2=${luku2##+(0)}; luku2=${luku2%%+(0)} 
#q=$(($luku1%$luku2));((q>1)) && q=$((10**$((${#q}-2)) )) || q=1 # siis q on jakojäännös esitettynä siten että ensimmäinen numero on 1 ja lopuista numeroista tulee nollia - viimeinen nolla poistettuna
luku1=$luku1'0000000000000000000'; luku1=${luku1:0:18} ;$tulosta " "$luku1 #"  "${#apu2}"  "$apu

for n in {1..5}; do # muodostetaan tulos-palasia 9 merkkiä kerrallaan
apu=$(($luku1/$luku2)); tulos[$n]=${apu}  # yksi keino palauttaa niitä kadonneita nollia;  (( $(($luku1%$luku2)) > $((10*$q )) )) && apu=$apu'0' on joskus tarpeen ja joskus liikaa
apu2=$(($luku1%$luku2)); luku1=$apu2'0000000000000000000'; luku1=${luku1:0:18} ; $tulosta " "$luku1"  "${#apu2}"  p"$apu
done

vanhatmerkit=1
for n in {1..5}; do # kootaan tulosta matriisin palasista
uudetmerkit=${#tulos[$n]}; [[ $uudetmerkit -lt $vanhatmerkit ]] && tulos[$n]=$nolliatulosteessa${tulos[$n]} ; vanhatmerkit=$uudetmerkit
tulos=$tulos${tulos[$n]}
done
 
#[[ ${tulos%%+(0)} -eq 1 ]] && nolliatulosteessa=${nolliatulosteessa:1} # purkkaviritys?
#echo "oikea tulos 54 desimaalilla esitetynä on päällä ja alla tulos tästä skriptistä"
#bc<<<"scale=$((${#tulos}+$((${#nolliatulosteessa})))); $1/$2" | tr -d '\\\n'; echo ' tämä rivi on bc:stä'
[[ $nolliatulosteessa ]] && echo .$nolliatulosteessa${tulos:0} || echo ${tulos:0:$kokonaisiatulosteessa}.${tulos:$kokonaisiatulosteessa} ;}

#---

function yhteenlasku () { # voi käyttää vähennyslaskuunkin
[[ ${1//[^-]/} ]] && m1=-1 || m1=+1; [[ ${2//[^-]/} ]] && m2=-1 || m2=+1
luku1=${1:0:18}
luku2=${2:0:18}
luku1=${luku1//[-+]/}; luku2=${luku2//[-+]/}
luku1=${luku1//-./-0.}; luku2=${luku2//-./-0.}
[[ ${luku1//./} == $luku1 ]] && luku1=$luku1".0" # on tarpeen että luvussa on yksi desimaalipiste
[[ ${luku2//./} == $luku2 ]] && luku2=$luku2".0" # joten lisätään sellainen mikäli ei jo ole
desimaaliosa1=${luku1##*.}; desimaaliosa1pituus=${#desimaaliosa1}
desimaaliosa2=${luku2##*.}; desimaaliosa2pituus=${#desimaaliosa2}
(( ${#desimaaliosa2} >= ${#desimaaliosa1} )) &&
{ apu=$desimaaliosa1"00000000000000000000"; desimaaliosa1=${apu:0:${#desimaaliosa2}} ;} || { apu=$desimaaliosa2"000000000000000000"; desimaaliosa2=${apu:0:${#desimaaliosa1}} ;}
#echo a$desimaaliosa2' 'b$desimaaliosa1 ; read # testatessa tämä on tarpeen
desimaaleja=${#desimaaliosa1} #; echo $desimaaleja
kokonaisluku1=${luku1%%.*}
kokonaisluku2=${luku2%%.*}
kokoluku1=$kokonaisluku1$desimaaliosa1 #; echo $kokoluku1
kokoluku2=$kokonaisluku2$desimaaliosa2 #; echo $kokoluku2
(( $m2 +1 )) && luku=$((10#$kokoluku1+10#$kokoluku2)) || luku=$((10#$kokoluku1-10#$kokoluku2))
echo ${luku:0: -$desimaaleja}.${luku: -$desimaaleja} ;}


# Varsinainen koodi:
x=.5; sin_x=$x;kerroin=$x;apu=$kerroin;  # skriptiin syötetty kulma radiaaneissa
kertoma=1;takanollia='';for n in {3..23..2}; do kertoma=$(($kertoma*$n*($n-1))); (( ${kertoma: -1} )) || { takanollia=$takanollia'0'; kertoma=${kertoma:0: -1} ;}; echo -n $kertoma' '$takanollia
  kerroin=$(kerro18 $x $( kerro18 $x $kerroin) ); echo -n '   '$kerroin;
  apu=$(jaa ${kerroin:0:17} ${kertoma:0:17}$takanollia ); echo -n '   '${tulos:0:25} 
  (( $n==19 | $n==15 | $n==11 | $n==7 | $n==3 )) && sin_x=$(yhteenlasku $sin_x -$apu) || sin_x=$(yhteenlasku $sin_x $apu); echo '  '$sin_x
done

- sitten siirrytäänkin siihen jakolaskun laajennokseen - se nimittäin vaikuttaa tähänkin paljon.
***

Tämä liukuvan-pilkun kertolaskuohjelma kerro9 on hitaampi kuin isoveljensä vaikka tämän tuloksessa saa olla vain 18 merkitsevää numeroa - muuten tuo hitaus johtuu uudesta käskystä nimeltä: seq sillä jo yksi uusi käsky romahduttaa nopeuden.

Tosin tämä on sittenkin BASH-skriptiksi todella nopea. Ja se hyväksyy paljon sellaista josta isoveli menee solmuun - esimerkiksi desimaalipisteeksi kelpaa sekä piste että pilkku - ja tieteelistäkin esitysmuotoa voi sisäänmenevissä luvuissa olla ja niissa voi eksponentin merkkinä olla joko iso tai pieni e. Ja ennenkaikkea skriptin toiminta on helpompi osoittaa oikeelliseksi.

Kun tekee skriptin mihin tehävään tahansa niin alkuunsa skriptin toiminta on yleensä kovin virheelistä. Mutta olipa virhe mikähyvänsä niin se on korjattavissa - ja itseasiassa nuo korjaukset parantavat koodia muutenkin. Mutta nyt on ihan liian myöhäistä yrittää saada tälläisista skripteistä matemaattisessa mielessä moitteettomia joten virtuoosit saivat tässäkin asiassa tahtonsa läpi eli saivat taas tuhottua BASH:ia vähäsen - ja pääsivät ketkut tästäkin tahallisesta teosta kuin koira veräjästä.

Vikojen korjaaminen käy jokaisen virheen jälkeen hitammaksi sillä jokaisen koodimuutoksen jälkeen täytyisi jokainen testi suorittaa uudestaan ettei vaan korjaa siten että joku aikaisemmin tehty lopettaisi oikeintoimimisen. Ja kun korjauksia tulee tarpeeksi monta niin joskus joutuu jopa aloittamaan ihan alusta - tämäkin skripti on aloitettu jo kolmasti uudestaan - kyllä jokainen yritys silti opettaa jotakin - en siis turhaan BASH:ia opetuskieleksi kutsu.

Vikojen korjaaminen nopeasti on liian myöhäistä tehdä tänäpäivänä sillä ne viat löytyisivät vasta yhteisön ponnistuksin ja nykyäänhän BASH-yhteisöt ovat pieniä eikä tämän tasoinen matematiikka kiinnostakaan enää juuri ketään. Mutta silloin aikoinaan BASH-yhteisöt olivat erittäin suuria ja tämmöiset kiinnnostivat monia joten nopeasti näistä olisi silloin oikeellisia tullut.
Koodia: [Valitse]
function kerro9 () { # Tuloksessa voi olla korkeintaan 18 numeroa - välittömästi desimaali-pisteen perässä olevia nollia ei lasketa mukaan eikä myöskään peränolia.
luku1=${1//./,}; luku1=${luku1//E/e}
luku2=${2//./,}; luku2=${luku2//E/e}
luku1=$(printf "%.18e" $luku1)
luku2=$(printf "%.18e" $luku2) #; echo $luku1' '$luku2; read
exp1=${luku1##*e}; exp1=${exp1//+0/+}; exp1=${exp1//-0/-}
exp2=${luku2##*e}; exp2=${exp2//+0/+}; exp2=${exp2//-0/-}
# exp3=$(($exp1+$exp2+1))

luku1=${luku1%%e*}; luku1=${luku1%%+(0)}
luku2=${luku2%%e*}; luku2=${luku2%%+(0)}

[[ ${luku1:0:1} = '-' ]] && { merkki1=-1; luku1=${luku1:1} ;} || merkki1=1
[[ ${luku2:0:1} = '-' ]] && { merkki2=-1; luku2=${luku2:1} ;} || merkki2=1 

kokonaisosa1=${luku1%%[,.]*}
kokonaisosa2=${luku2%%[,.]*}
kokonaistentulo=$(($kokonaisosa1*$kokonaisosa2))
kokonaisia=${#kokonaistentulo}
exp3=$(($kokonaisia+$exp1+$exp2)) #; echo $exp3; read

# echo; bc<<<"$1*$2" # bc kertoo useasti lopputuloksen joka on ihan varmasti oikea ja siihen on kiva verrata. Mutta tässä on paljon sellaistakin josta bc kirjoittaa vain härskin viestin.
tulos=$((${luku1//,/}*${luku2//,/}))'00000000000000000000000000000000000000'; [[ ${kokonaistentulo:0:1} -eq 9 ]] && [[ ${tulos:0:1} -eq 1 ]] && exp3=$(($exp3+1))
[[ $(($merkki1*$merkki2)) -eq -1 ]] && echo -n '-'
[[ $exp3 -gt -1 ]] && apu2=${tulos:0:$exp3}.${tulos:$exp3} ||  apu2=.$(printf '0%.s' $(seq ${exp3:1}))${tulos%%+(0)}
[[ ${apu2//[^.]/} ]] && apu2=${apu2%%+(0)}; echo ${apu2%.} ;}


# kohtia jotka kannattaa tarkistaa:
kerro9 1 1
kerro9 -1 1
kerro9 -1 -1
kerro9 1 -1
kerro9 0 0 
kerro9 1.1 1,1                                       # on parempi että laskutoimitus onnistuu vaikka se ei teoriassa ihan oikein olekaan.
kerro9 4 4
kerro9 1000001.2345 1E-5

kerro9 1234567891 1234567892
kerro9 123456789012345678 2.2
kerro9 123.4567891 1234567.89
kerro9 1234567891 1234567892E-118                  # kerrottavien esitysmuoto saa olla tieteellinenkin
kerro9 .0000000000001234567892 .000000001234567891 # välittömästi desimaalipisteen perässä olevia nollia ei lasketa merkkilukuun.
kerro9 12345678000000000000 123456780000000000000  # peränollatkaan eivät ole merkitseviä nomeroita
 
kerro9 3.16227766 3.16227766                       # dekadin vaihtuminen ulostulosssa on syytä tarkistaa, siis se että kun
kerro9 3.16227767 3.16227767                       # ulostulo siirtyy uuteen dekadiin muuttuuko desimaaalipisteen paikka oikealla hetkellä
kerro9 10 100
 
kerro9 1000000001 .999999999
kerro9 +1234567891 1234567892                       # + merkkiä voi käytää osoittamaan luvun positiivisuutta eikä sitä silloin käsitetä laskutoimitukseksi.
kerro9 123.4567891 1234567.89

***

Ei kukaan viitsi tehdä noilla vanhoilla käskyillä skriptiä jos tietää että kun tekee koodia päivän joutuu kommentoimaan sitä viikkoja - sitäpaitsi kommenttejakin pitäisi selventää omilla kommenteillaan - lisäksi minulla on sellainen käsitys että jos kommentointi on moitteeton, vuokaaviot on tehty ja vertaisarvioita hankittu niin kukaan ei edes lue niitä - saatika ymmärrä kommentteja oikein jos skriptiä täytyy korjata. Melko turhaa touhua koko kommentointi. Tämä johtaa tosin siihen että myöhemmin ei korjata vaan tehdään uusi - mutta homma pelaa edes jotenkin.

Myös printf on hidas uusi käsky. Näillä uusilla massivisilla käsky-järkäleillä on sekin paha piirre että niillä on ne ominaisuudet mitkä niillä on ja jos käsky ei miellytä niin asialle ei voi tehdä mitään. Mutta jos uusia käskyjä jäljitellään vanhojen nopeiden käskyjen joukolla niin ominaisuudet voi muodostaa aivan millaiseksi haluaa - esimerkiksi voi tehdä käskyn: printf2 jolla on printf:n ne ominaisuudet jotka ovat tarpeen senhetkisessä hommassa - ja kenties hieman uusiakin ominaisuuksia - ja lopputulos on silti nopea. Mutta vasta monien versioiden jälkeen toiminta on juuri haluttu.

Tässä on tarkoitus ainoastaan matkia sitä kuinka printf kykenee tekemään sisäänmenevät luvut 'saman-näköisiksi' sillä esimerkiksi äsköinen skripti ei enempää kaipaa.  Ensimmäinen versio voisi olla vaikka:
Koodia: [Valitse]
function fprint2 () { luku1=${1##+(0)}; [[ -z "${luku1##*e*}" ]] && { exp1=$((${luku1##*[eE]})); luku1=${luku1//e*/} ;} || exp1=0; [[ ${luku1:0:1} = . ]] && { apu=${luku1%%[1-9]*}; exp1=$(($exp1-${#apu})); luku1=${luku1##*[.0]} ;} || exp1=0 ; luku1=${luku1//./}; echo ${luku1:0:1}.${luku1:1}e$exp1 ;}

# kokeet (luvullahan ei enää ole etumerkkiä):
luku1=1234.56e8; fprint2 $luku1
luku1=1234.56; fprint2 $luku1
luku1=.123456e-8; fprint2 $luku1
luku1=0.123456e-8; fprint2 $luku1
luku1=.0000123456e-8; fprint2 $luku1 # koska printf hyväksyy tämmöisiä kummallisia lukuja niin printf2:n on syytä hyväksyä ihan samanlaisia kummajaisia.
luku1=1; fprint2 $luku1
luku1=11; fprint2 $luku1

***
- nyt meni tuon printf:n kanssa miettimiseksi ja välillä kannattanee tehdä jotakin muuta.

- ei näillä laskuilla ole toistaiseksi muuta tehtävää kuin osoittaa ettei pitäisi sanoa: BASH ei osaa .... -  ja onhan nämä hyvää dementian torjumista.

- jos matemaatikkoja ei päästetä esittämään derivaattoja ja limeksiä niin e:n laskeminen Taylorin sarjakehitelmällä on todella yksinkertaista: e=1+1+1/2!+1/3!+1/4! .....

- sen kykenee laskemaan aivan tavanomaisin keinoinkin, mutta silloin tuloksessa  on kovin vähän numeroita ja laskenta on hidasta:
Koodia: [Valitse]
kerroin() { (( $1 )) && echo $(( $1 * $(kerroin $(($1 - 1))) + 1 )) ;}
summa() { apu=$(echo $(( 10**($1-1) * $(kerroin $1) / $(($(seq -s* $1))) ))) ;}
time for i in {1..11}; do summa $i; done; echo 'e='2.${apu:1}

Mutta desimaalilaskentaa käyttäen e:hen saa paljon enemmän numeroita ja nopeamminkin:

« Viimeksi muokattu: 01.11.23 - klo:11.24 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #37 : 13.11.23 - klo:11.19 »
Ensiksi täytyy kuitenkin kirjoittaa uusiksi neliöjuuren laskeminen tieteellisestä esitysmuodosta sillä aikaisempi skripti ei useissa koneissa toiminut - tämän pitäisi toimia. Sitäpaitsi uuden version tuloksessa kaikki numerot ovat oikeita - matemaattisesti se merkitsee että viimeisessä numerossa on vain +-0.4999... epävarmuus. Kummallista; jo toinen tapaus jossa BASH on aina täysin oikeassa numeromääränsä puitteissa.

Neliöjuuren laskeminen BASH:in omilla peruskäskyillä on nopeampaa kuin matematiikkaohjelmilla mutta varjopuolena on että tuloksessa on vain 9 numeroa. Neliöjuuri voidaan laskea
kuinkamoni-numeroisesta luvusta tahansa mutta vain 18 merkitsevintä numeroa huomioidaan. Luku voi siis olla olla tyypiltään yhtähyvin:

.0000000000000000000000000000000000000000000000000123456789012345678900000000e+357, 1234567890123456789012345678901234567890123456789000000000000000000000000000e-52 tai yksinkertainen luku 4. Luku josta neliöjuuri otetaan saa olla joko normaalissa tai tieteellisessä esitysmuodossa mutta tulos esitetään aina tieteellisessä esitysmuodossa.

Printf kuuluu uusiin käskyihin ja se on tällaisessa käytössä hyvin hidas. Sen saisi kyllä korvattua joukolla vanhoja nopeita käskyjä mutta muunnoksen tekemisessä olisi kova homma eikä nyt ole aikaa sen tekemiseen - se olisi kyllä yli kaksikertaa nopeampi printf.

Printf on 50 kilo-sanan järkäle joka sössii usein - myös desimaalipisteen kanssa. Aikaisemmassaskriptissä korjasin printf:n käytöstä käskyllä: LANG=C mutta sekään ei tunnu aina toimivan. Muutinkin sen käskyksi: LC_NUMERIC=C joka toimii paremmin.

Kyllähän tämänkin skriptin voi sijoittaa luokkaan temput - eikä tämä olisi muissa kielissä edes hyvä. Mutta sikäli tämä on mielenkiintoinen että BASH:in omat virtuoosit koettavat epäilyttävin keinoin estää tämmöisien skriptien tekemisen BASH:iin. Mieleen tulee että virtuoosit hylkäsivät BASH:in luulojen perusteella ja nyt he yrittävät piilottaa hölmöilynsä.

Koodia: [Valitse]

function sqrt () {
apu=$(LC_NUMERIC=C printf "%.17e\n" $1); mant=${apu%%e*};apu=${apu##*e}; (( $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 ${sqrt:0:1}.${sqrt:1}e$expo ;}

juurrettava=27.34567890123456789;time sqrt $juurrettava

***

Nyt kun BASH on melkein kuollut olisi entistä tärkeämpää että kaikki rakentaisivat BASH:ia yhdessä. Ei se ole rakentavaa yhteistyötä että kukaan haukkuu ketään - joten perun aikaisempia väitteitäni: eivät virtuoosit ole hölmöjä vaan halusivat vaan aikanaan muita kieliä korvaamaan BASH:ia sillä BASH on ihan liian vaikea kieli kaikille, myös virtuooseille.

Virtuoosit halusivat siis aikoinaan päästä BASH:ista eroon ja sehän olisi ollut paljon vaikeampaa mikäli BASH:in huomattaisiin toimivan desimaalilukujenkin kanssa ihan hyvin. Mutta tuhoamis halustaan huolimatta virtuoosit eivät ole koskaan sanoneet että desimaalilaskut eivät BASH:illa onnistu - he ovat sanoneet vain että BASH:in matematiikkamoottori ei desimaaleja hyväksy ja sehän on kiistaton tosiasia - ja tosiasia on sekin ettei BASH tunne desimaali-lukutyyppiäkään. Mutta desimaalilaskut lasketaan aina muutenkin kokonaisluvuilla - siis myös matematiikkaprosessoreissa numerot lasketaan kokonaislukulaskimella ja desimaalipisteen paikkaa ylläpidetään erikseen ja kokonaisuutta kutsutaan liukuvan pilkun laskimeksi. Kun BASH:in suhteen tätä ei ole koskaan käyttäjille kerrottu niin virtuoosit ovat itseasiassa johdatelleet käyttäjät tekemään virhepäätelmän siitä ettei desimaaleilla voi laskea - ja jotta varmistuisi ettei kukaan edes epäilisi desimaalilaskujen toimivan tehtiin desimaalilaskuihin soveltumattomia muutoksia käskykantaan, annettiin 'kirjastokielto', väitettiin eval-käskyä pahikseksi - ja väitettiin BASH:ia muutenkin hampaattomaksi ettei kukaan vaan kokeilisi mitään.
- itseasiassa jokaisessa BASH:issa on kirjasto vaikkei siitä koskaan puhuta. Löydät sen käskyllä: declare -f .
- jokaisessa ~/.bashrc-tiedostossa on perus-asennuksessakin todennäköisesti muutama eval-käsky.
- ei desimaali-lukutyyppiä tarvitsekaan olla sillä desimaalilukuhan on sama kuin kaksi kokonaislukua joiden välissä on desimaalipiste - ja desimaalipisteen erottamat kokonaisluvut ovat täysin erillisiä eikä toisen arvo vaikuta toisen arvoon muulloin kuin laskutoimituksissa - joissa vaikutuksen huomioiminen on ysinkertaista. Tekstijonoa voidaan käsitellä myös matemaattisesti mikäli käsiteltävän tekstijonon palanen on ulkoasultaan matematiikka-moottorin hyväksymä kokonaisluku - desimaalilukua voi siis käsitellä kun se jaetaan kahteen kokonaislukuun desimaalipisteen kohdalta ja käsitellään kumpaakin puoliskoa erikseen. Laskutoimituksissa saattaaa syntyä luku joissa desimalipuolelta joutuu hylkäämään ensimmäisen numeron ja lisäämään sen kokonailuvun puolelle - tai muodostamaan luvusta yhden komplementin ja hylkäämällä etumerkin - ja vähentämällä kokonaiosasta yksi.
- mikäli kokonaisluku lyhyempi kuin 18 merkkiä ei ole mitään ongelmaa mutta jos se on pidempi kuin 18 merkkiä jaetaan se palasiin - noiden palasten käsittely on kovin monivaiheista mutta onnistuu sekin.
- päinvastoin tekstijono on paljon parempi kuin desimaaliluku sillä siinähän voi olla merkkejä kuinkamonta tahansa.
- mikäli käsitellään palasiin katkottua lukua saattaa toinen luku alkaa nollalla. Koska BASH mieltää nollilla alkavat luvut oktaaliluvuiksi täytyy palasen eteen kirjoittaa: 10# jotta toimittaisiin jokatapauksessa desimaalijärjestelmässä.

Ja entäpä sitten funktio-parametrit: BASH:in ominaisuus on se että koko skriptin alueella tunnetaan jokaikinen muuttuja joka on määritelty jossakin. Mutta kun mainitaan joku nimi ei se vielä tee siitä muuttujaa: yleensä muuttuja muodostetaan siten että kun nimi mainitaan tarkoituksella että siitä tulisi muuttuja niin kirjoitetaan pääohjelmassa oltaessa: muuttujan_nimi=arvo - mutta funktiossa niin ei voi enää tehdä (esimerkiksi käsky $$parametri_numero=arvo ei toimi). Jos funktioon annetaan muuttuja on se tullessaan vain tekstijono eikä muuttuja - vaikka se olisi alunperin ollutkin muutuja. Mutta sen saa yhdistettyä kutsujan saman-nimiseen muuttujaan jollain käskyistä:
1. numero-muuttujan tapauksessa: let $parametri_numero=arvo
2. tekstijono-muuttujan tapauksessa: read<<<$parametri_numero arvo.
3. BASH lisäksi antaa kirjanpitonsa skriptaajien käyttöön declare-käskyn avulla (ja sallii myös kirjoittaa sinne kirjanpitoon). Ja sitäkautta onkin matriisit viisainta yhdistää nimeen - toimii keino kyllä muillekin muuttujatyypeille.
- yhteenvetona: virtuoosien väitteet etteivät nimiparametrit toimi on pahantahtoinen tulkinta: ne toimivat ihan loistavasti vaikkakin varsin epäsovinnaisesti. Arvoparametreja sensijaan ei useinkaan kannata käyttää vaan toimia nimiparametreilla sillä nimiparametrit huolehtivat parametrin palautuksesta automaattisesti -> mitään ei tehdä mutta silti parametri on 'palautettu' elikä se on muuttunut pääohjelman muistissa. Siis BASH on taas paljon parempi kuin muut kielet - funktioon ei kuljeteta yhtään arvoa eikä myöskään palauteta mitään elikä ei hukata aikaa hommiin jotka on tehty jo.
- voitaisiin kirjoittaa myös: 'eval \$$parametri_numero' mutta virtuoosit torppasivat tämän keinon väittämällä BASH:in toteutusta eval-käskystä pahikseksi - muissa kielissä eval on hyvis.
- virtuoosit ovat perillä siitä että BASH toimii näin eikä sen tarvitse parametreja palauttaa - mutta silti he väittävät edelleen että BASH ei osaa parametreja palauttaa sillä onhan se kirjaimellisesti ottaen ihan totta. Ovat vain vaiti siitä ettei BASH:in tarvitsekaan parametreja palauttaa käytettäessä nimiparametreja - ja koska 'palautus' ei toimi ihan normaalikonstein niin taas kertaalleen on saatu käyttäjät huijaamaan itseään.

- mutta eivät ne eri funktioiden muuttujat aina yhteisiä ole sillä kyllä BASH:issakin tunnetaan paikalliset muuttujat. Lisää vain funktion alkuun lauseen: local muuttuja. Silloin sitä muuttujaa ei tunneta missään muualla - ja toisessa funktiosssa saman niminen muuttuja on täysin eri muuttuja.
- paikallisten muuttujien erikoistapaus on se kun funktio kutsuu itseään. Silloin jokaisen kutsukerran muuttujat ovat ilmanmuuta paikallisia. Tätä rekursiota ei muuten yleensä kannata käyttää sillä se on erittäin hidas ohjelmarakenne - huomasin juuri äsken ettei se muuten olekaan hidas mikäli sitä käyttää siten että tuo rekursio tapahtuu C:ssä - etsipä toteutustapaa näistä kertomuksista yksinkertaisten sqrt funktion toteutuksista.

Samoin skriptien hitauskin on osin tehtyä: skriptit on jo alunperin opetettu kasaamaan väärin ja käyttämään vääräntyyppisiä käskyjä: oikein tehty skripti kutsuu tulkkia vain kerran tai muutaman - mutta väärintehty skripti kutsuu tulkkia lukemattomia kertoja ja siihen se aika kuluu - tulkkaustulos toimii C:ssä ja siellä toiminta on aina nopeaa.

Muihin kieliin verrattuna BASH on sittenkin kelvottoman hidas ja muutenkin omituinen - tuskinpa siitä saa edes välttävän hyvää kieltä vaikka kuinka kaivelisi sen hyviä puolia esiin. Mutta näin ei ollut silloin kolmekymmentä vuotta sitten kun BASH:in rappio alkoi - sillä nämä kaikki olisivat toimineet jo silloin.

Kyllä BASH:ia silti yksi ukko, Chet Ramey, kehittää jatkuvasti ja hyvää työtä hän tekeekin (kai hänellä on tukijoukkojakin?). Luepas BASH 5.2:n uusista ominaisuuksista verkkosivulta: http://tiswww.case.edu/php/chet/bash/NEWS. Jo ensimmäinen käsky saa epäilemään mistä kielestä on kyse sillä käsky on: malloc. Mutta toisaalta BASH:in käskyttääkin C:tä -> BASH:in malloc on siis ohje kääntäjälle kuinka toimia sillä C:n oma malloc mählii BASH skripteissä.

BASH ei ole saanut koskaan mahdollisuuttakaan kehittymiseen vaan yrityksetkin on torpattu. Mutta edistys ei kavahda ketään - skriptin merkittävimmät kriteerit ovat: toimiiko skripti ja vahingoittaako se ympäristöään. Tuo vahingoittaminen pitää kyllä nykyään varmaankin paikkansa sillä onhan BASH:ia laiminlyöty melkein täysin yli kolmekymmentä vuotta.

Mutta keksijä ja kokeilija ei tosiaankaan ole oikea henkilö saattamaan kieltä iskukykyiseksi, ainoastaan virtuoosit siihen kykenisivät.

***
Desimaalilukujen potenssiin korottaminen onnistuu myös hyvin, tosin toistaiseksi vain positiiviset kokonaislukupotenssit toimivat - mutta jopa desimaaliset potenssit toimisivat, kylläkin erittäin hitaasti logaritmien kautta jos vain tekisi tarvittavan kutsun jo tehdyille monille funktioille - mutta se on BASH:issa niin sotkuinen homma että se kaipaa ihan omaa tarinaansa - negatiiviset potenssit alkaisivat nekin toimia silloin.

Aikalailla vanhan kertaustahan tämä on ja tässä on vain vähän uutta - mutta on pakko käydä tämmöisetkin skriptit läpi sillä vasta tämmöisten jälkeen voi aavistella kuinka toimintaa voisi ehkä parantaa. 

Aikaa potenssiin korotuksessa kuluu suurinpiirtein potensin numeroarvon verran millisekunteja elikä BASH skriptiksi toiminta on nopeaa - vaikka muihin kieliin verrattuna toiminta on todella hidasta niin BASH:in kannalta se on jo paljon että homma onnistuu edes hitaasti.

Potenssiin korotettavat luvut katkaistaan 18-numeroisiksi. Ja tuloksen tarkkuus laskee siitäkin pahimmillaan luokkaa numero jokaista potenssin numeroa kohti - joten esimerkiksi kymmenenteen potenssiiin korotettaessa voi pahimmillaan olla täysin varma vain 14:stä oikeasta numerosta - harvoin niin huonosti tosin käy. Ja joskus virhe on mitätön suuremmillakin potensseilla.

Mutta sitten itse skripti (kaikki kirjasto-ohjelmat on syytä liittää mukaan. Tai voisihan nuo funktiot kirjoittaa tiedoston : ~/.bashrc:n perään jolloin ne olisivat aina käytettävissä):

Koodia: [Valitse]
function kerro18 () {
tulosta=: # yhdessä paikassa päätetään tulostetaanko monessa paikassa välituloksia. Vaihtoehdot:tulosta=echo ja tulosta=:
luku1=${1:0:18}; luku2=${2:0:18}
# [[ ${#1} -gt 18 || ${#2} -gt 18 ]] && echo laskettavissa liikaa numeroita && return
$tulosta "annetut numerot: $1 $2"
[[ ${1:0:1} = - || ${2:0:1} = - ]]  && merkki=- || merkki=''
[[ ${1:0:1} = - && ${2:0:1} = - ]]  && merkki=''
apu1=${luku1//\-/}; apu2=${luku2//\-/}
desimaaliosa1=${luku1##*.};
desimaaliosa2=${luku2##*.};
[[ ! ${apu1//[^.]/} ]] && desimaaliosa1=''
[[ ${apu1//[^.]/} ]] && { luku1=${apu1:0:18}; kokonaisluku=0 ;} || { luku1=${apu1:0:18}"."; kokonaisluku=1 ;}
[[ ! ${apu2//[^.]/} ]] && desimaaliosa2=''
[[ ${apu2//[^.]/} ]] && { luku2=${apu2:0:18}; kokonaisluku=0 ;} || { luku2=${apu2:0:18}"."; kokonaisluku=$(( 1 & $kokonaisluku )) ;}
 desimaaleja=$((${#desimaaliosa1}+${#desimaaliosa2})); $tulosta desimaaliosa1:$desimaaliosa1"   desimaaliosa2:"$desimaaliosa2"   desimaaleja:"$desimaaleja
luku1=000000000000000000${luku1//./}
luku2=000000000000000000${luku2//./}
a=${luku1: -18:9}; b=${luku1: -9}
c=${luku2: -18:9}; d=${luku2: -9}; $tulosta $a' '$b; $tulosta $c' '$d
luku1=00000000000000000000000000000000000000$((10#$b*10#$d))
luku2=00000000000000000000000000000000000000$((10#$d*10#$a))"000000000"
luku3=00000000000000000000000000000000000000$((10#$c*10#$b))"000000000"
luku4=00000000000000000000000000000000000000$((10#$a*10#$c))"000000000000000000"
luku1=${luku1: -36} ; $tulosta $luku1
luku2=${luku2: -36} ; $tulosta $luku2
luku3=${luku3: -36} ; $tulosta $luku3
luku4=${luku4: -36} ; $tulosta $luku4; $tulosta
luku11=${luku1:0:18}
luku12=${luku1:18}; $tulosta a$luku11' 'b$luku12
luku21=${luku2:0:18}
luku22=${luku2:18}; $tulosta c$luku21' 'd$luku22
luku31=${luku3:0:18}
luku32=${luku3:18}; $tulosta a$luku31' 'b$luku32
luku41=${luku4:0:18}
luku42=${luku4:18}; $tulosta c$luku41' 'd$luku42;$tulosta
summa1=$((10#$luku12+10#$luku22+10#$luku32+10#$luku42)); $tulosta summa1:$summa1
summa1pituus=${#summa1}; ylivuoto=0; (( $summa1pituus >= 19 )) && ylivuoto=${summa1:0: -18} && summa1=${summa1:1}
summa1=000000000000000000$summa1; summa1=${summa1: -18} ;$tulosta ylivuoto:$ylivuoto' summa1:'$summa1
summa2=$((10#$luku11+10#$luku21+10#$luku31+10#$luku41+$ylivuoto)); $tulosta summa2:$summa2
# echo; echo tulos laskusta: $1 \* $2'  . Ylärivi on bc:stä ja alarivi tästä skriptistä:'
# bc<<<"scale=40; $1*$2"
(( $summa2 )) && : || summa2=000000000000000000
(( $kokonaisluku )) && tulos=${summa2/*(0)/}$summa1 || { apu=$summa2$summa1; tulos=${apu:0: -$desimaaleja}.${apu: -$desimaaleja} ;}
echo $merkki${tulos##+(0)} ;}

function potenssi () { # varsinainen potenssiin korottaminen
apu=$( kerro18 $1 $1 )
for (( n=2; n<$2; n++ )); do
apu=$( kerro18 $apu $1)
done
[[ $1 = 0 ]] && { apu=1; [[ $2 = 0 ]] || apu=0 ;} # sopimus on että:  0 ^ 0 = 1 - mutta 0 mihin tahansa muuhun potenssiin on nolla
echo; echo "lasku on: $1^$2"
echo -n "bc:n laskema varmasti oikea tulos: ";bc -l<<<"$1^$2"
echo    "tämän  skriptin   laskema   tulos: $apu" ;}

time potenssi 1507.5 5 # tämä on merkintätapa laskulle: 1507.5^5. Jos laskun haluaa tehdä jossain skriptissä niin merkintatapa on: luku=$(1507.5^5).
# luku ei ole desimaaliluku vaikka se siltä  näyttääkin vaan se on tekstijono.
 
time potenssi 2.5 30
time potenssi -2 2
time potenssi -2 3
time potenssi 9.999999 18 # tarkkuus huononee suunnattomasti
time potenssi 0.987654321098 10

Siis skriptiä kokeillaan siten että maalataan sen aivan kaikki lauseet koodista kerralla täältä verkkosivulta ja liimataan ne pc:n päätteeseen ja painetaan return. Vain BASH skriptit toimivat tällätavoin.
- kokeillessa älä haaveilekaan tiedostosta, suoritus oikeudesta tai käskystä !#/bin/bash. Käyttäjiä tylytetään niillä.


« Viimeksi muokattu: 25.11.23 - klo:14.46 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #38 : 28.11.23 - klo:13.00 »
Potenssiin korotus nopeutui yli kaksinkertaisesti skriptin rakennetta yksinkertaistamalla - nyt potenssiin korotus on yksi funktio. Pienet potenssit lasketaan aina alle 10 millisekunnin.
Eihän tämä vieläkään ole kovin käyttökelpoinen mutta toimii edes jotenkin ja toisaalta sekä nopeus että tarkkuus paranevat kokoajan. Mutta sriptien ominaisuudet paranevat aina kovin hitaasti - sillä jos koettaa kiirehtiä niin homma leviää helposti käsiin - toiminta on sama kuin hiihtomäessä: kun nopeus alkaa kiihtyä kovin nopeaksi niin takapuoli maahan tai jotain muuta hidastetta. Mutta jos jaksaa niin toiminta tuntuu paranevan ikuisesti.

Ja yleensä jossain vaiheessa tulee loikka suorituskyvyssä; tämmöinen nopeuden kaksinkertaistuminen on pientä. Sillä tuntuu olevan niin että jokaisessa asiassa on rajaton määrä ratkaisutapoja - ja meille on opetettu niitä tehottomia ratkaisutapoja. Pitää täysin paikkansa että kokeillessa paljon tulee helposti siirryttyä epäilyttäville alueille - mutta toisaalta jos skripti toimii aina luotettavasti ja vahingoittamatta ympäristöään niin mitä pahaa siinä kokeilemisessa on?

Määränpäänä on koota funktioista kirjasto josta kukahyvänsä voi hakea koneeseensa funktioita ilman että tulisi myrkytetyksi kekseillä, kirjautumatta ja asentamatta mitään ettei kone muuttuisi mitenkään - sillä kaikilla meillä on taipumus temppuhin - eihän siinä mitään mutta kun tuputamme niitä temppuja toisillekin. Hommaa kuvaa mietelause: miksi tehdä helpolla kun voi tehdä vaikeasti?

Hyvän kirjaston yksi ominaisuus on se että se toimii kaikissa tehtävissä samankaltaisin menetelmin eikä kovin usein muuta toimintaansa. Kirjaston kokoaminen onkin todella hidasta - jos keskittyisi yhteen pieneen tehtävään niin vuosi kuluisi kumminkin. Siis kirjaston kokoaminen olisi pitänyt alkaa jo silloin kolmekymmentä vuotta sitten - niin se taisi alkaakin mutta koko kirjasto-idea romutettiin sittemmin.


function potenssi () {
tulosta=: # yhdessä paikassa päätetään tulostetaanko osa-tehtävien jälkeen välituloksia. Vaihtoehdot:tulosta=echo ja tulosta=:
for n in $(seq $(($2-1))); do
luku1=${1:0:18}; [[ $n = 1 ]] && luku2=$luku1 || luku2=$merkki${tulos##+(0)}; luku2=${luku2:0:18}
$tulosta "annetut numerot: $1 $2"
[[ ${1:0:1} = - ]]  && merkki=- || merkki=''
[[ ${1:0:1} = - && ${2:0:1} = - ]]  && merkki=''
apu1=${luku1//\-/}; apu2=${luku2//\-/}
desimaaliosa1=${luku1##*.};
desimaaliosa2=${luku2##*.};
[[ ! ${apu1//[^.]/} ]] && desimaaliosa1=''
[[ ${apu1//[^.]/} ]] && { luku1=${apu1:0:18}; kokonaisluku=0 ;} || { luku1=${apu1:0:18}"."; kokonaisluku=1 ;}
[[ ! ${apu2//[^.]/} ]] && desimaaliosa2=''
[[ ${apu2//[^.]/} ]] && { luku2=${apu2:0:18}; kokonaisluku=0 ;} || { luku2=${apu2:0:18}"."; kokonaisluku=$(( 1 & $kokonaisluku )) ;}
 desimaaleja=$((${#desimaaliosa1}+${#desimaaliosa2})); $tulosta desimaaliosa1:$desimaaliosa1"   desimaaliosa2:"$desimaaliosa2"   desimaaleja:"$desimaaleja
luku1=000000000000000000${luku1//./}
luku2=000000000000000000${luku2//./}
a=${luku1: -18:9}; b=${luku1: -9}
c=${luku2: -18:9}; d=${luku2: -9}; $tulosta $a' '$b; $tulosta $c' '$d
luku1=00000000000000000000000000000000000000$((10#$b*10#$d))
luku2=00000000000000000000000000000000000000$((10#$d*10#$a))"000000000"
luku3=00000000000000000000000000000000000000$((10#$c*10#$b))"000000000"
luku4=00000000000000000000000000000000000000$((10#$a*10#$c))"000000000000000000"
luku1=${luku1: -36} ; $tulosta $luku1
luku2=${luku2: -36} ; $tulosta $luku2
luku3=${luku3: -36} ; $tulosta $luku3
luku4=${luku4: -36} ; $tulosta $luku4; $tulosta
luku11=${luku1:0:18}
luku12=${luku1:18}; $tulosta a$luku11' 'b$luku12
luku21=${luku2:0:18}
luku22=${luku2:18}; $tulosta c$luku21' 'd$luku22
luku31=${luku3:0:18}
luku32=${luku3:18}; $tulosta a$luku31' 'b$luku32
luku41=${luku4:0:18}
luku42=${luku4:18}; $tulosta c$luku41' 'd$luku42;$tulosta
summa1=$((10#$luku12+10#$luku22+10#$luku32+10#$luku42)); $tulosta summa1:$summa1
summa1pituus=${#summa1}; ylivuoto=0; (( $summa1pituus >= 19 )) && ylivuoto=${summa1:0: -18} && summa1=${summa1:1}
summa1=000000000000000000$summa1; summa1=${summa1: -18} ;$tulosta ylivuoto:$ylivuoto' summa1:'$summa1
summa2=$((10#$luku11+10#$luku21+10#$luku31+10#$luku41+$ylivuoto)); $tulosta summa2:$summa2 
(( $summa2 )) && : || summa2=000000000000000000
(( $kokonaisluku )) && tulos=${summa2/*(0)/}$summa1 || { apu=$summa2$summa1; tulos=${apu:0: -$desimaaleja}.${apu: -$desimaaleja} ;}
done
echo; echo tulos laskusta: $1 \^ $2'  . Ylärivi on varmasti oikea arvo bc:stä vertaamista varten ja alarivi tästä skriptistä:'
bc<<<"scale=20; $1^$2"
(( $2 & 1 )) && echo -n $merkki; echo ${tulos##+(0)} ;}

time potenssi -1.23456789012345 10 # tämä on BASH:in merkintätapa laskulle: -1.23456789012345^10. Jos laskun haluaa tehdä jossain skriptissä niin siinä skriptissä merkintatapa on: luku=$(-1.23456789012345 10)

petteriIII

  • Käyttäjä
  • Viestejä: 657
    • Profiili
Vs: Skriptiajuri
« Vastaus #39 : 05.12.23 - klo:15.27 »
Keskenkaiken mieleeni tuli että desimaalilaskennan toimiminen kertoo sen että myös suoritusajan mittaus toimisi samoja menetelmiä soveltaen paljon paremmin - joten käsitelläänpä suoritusajan mittausta nyt uudestaan sillä sen käsittely oli aikoinaan kovin epämääräistä.

On totuttu siihen ettei millisekuntia tarkemmin kannata mitään BASH:issa suoritusaikoja ajoittaakaan sillä suoritusajat vaihtelevat aina vähintään joitain millisekunnin kymmenyksiä ja tulkin kutsuminenkin ja sen toimintakin kestää jotain pientä ja epämääräistä - muuten näiden syiden takia BASH:in time-käsky ilmoittaakin erikseen user, sys ja system ajat - ja se aika joka kestää tuloksen selviämiseen kuluu taitaa olla näiden aikojen jonkinsortin summa.

Kaikki lähtee siitä kuinka kauan kestää 'nollasuoritus' elikä käsky: kaksoispiste - joka ei tee mitään mutta tulkkia siinä kyllä kutsutaan. Nollasuorituksen kestoajan luotettava mittaaminen helpottuu oleellisesti kun hyödyntää BASH:in kykyä käsitellä jopa samassa lauseessa käsiteltyä tekstijonoa laskettaessa kokonaislukuna. Vaikka kestoaikaa voi kuvata ainoastaan desimaaliluvulla niin sehän on  kokonaisluku kunhan vaan jättää desimaalipisteen kirjoittamatta - joten laskut onnistuvat ihan hyvin - kunhan vain ottaa huomioon montako niitä desimaaleja pitäisi olla. Mutta tulosten loppukäsittelystä ei tulisi mitään ilman noita vanhoja jo unohdettuja käskyjä joiden erinomaisuutta ei koskaan tajuttu - joten kunnollista ajoitusta ei ole ennen tehty - tai onhan parempi ajoitustapa toki jo aikaisemminkin tunnettu mutta keinoja sen kunnolliseen käyttöön ja oikeellisuuden osoittamiseen ei ole ollut. 
 
Nollasuorituksen kunnollinen ajoitus:
Koodia: [Valitse]
alkuhetki=$(date +%s%N); : ; loppuhetki=$(date +%s%N); aika=$((10#$loppuhetki-10#$alkuhetki)); apu=000000000$aika; apu=${apu: -14: -9}.${apu: -9}; echo ${apu##+(0)} 
- luultavasti käsky: $(date +%s%N) ei ole tarkka. Mutta se tekee suurinpiirtein saman virheen kaksi kertaa: ensimmäisellä kerralla se vaikuttaa plussana ja toisella miinuksena joten ne kumoaa toisensa melkohyvin.
- nollasuoritus on tuo yksinäinen kaksoispiste seuraavan kohdan lopussa: alkuhetki=$(date +%s%N); : 
- nollasuorituksen suoritusaika on oikeastaan aika suuri - paljon suurempi kuin mitä saa kun antaa käskyn: time :  . Miksi time-käsky antaa liian pienen ajan? Vika on nimittäin time-käskyssä sillä tuo tarkka ajoitus on varmasti tarkka - ei varmaankaan nanosekunnilleen mutta yli mikrosekunnilleen. Selitys time käskyn liian pieneen aikaan on se että time-käskyn  real-, user- ja system-ajat ovat pienempiä kuin .0005 joten ne tulkitaan nolliksi - siksi time-käskyn ajoitustulos on lähes millisekunnin liian pieni sillä oikea aika on niiden summa; kyseessä on siis pyöristysvirhe.
- äskeisen selityksen oikeellisuuden varmitus: kirjoita kaksoispisten paikalle: time sleep .001 . Saat kaksi erilaista aikaa. Mutta huomaapa että time-ajoituksen real+user on lähes sama kuin tarkempi ajoitustulos. Joten ei niitä aikaisemmin mainittuja millisekunnin kymmenyksiä oikeastaan ole ollutkaan - lisäksi on unohdettu jo kauan sitten kuinka time-käskyn tulokset tulkitaan.
- kaksoispisteen paikalle voi kirjoittaa mitähyvänsä: yksittäisiä käskyjä, skriptejä tai funktiokutsuja - ja mitä sinne laitetaankin niin sen toiminta-aika määritellään.
- koska tuloksista voi muodostaa keskiarvoa niin esimerkiksi voi vihdoinkin lopullisesti selvittää kumpi käsky on keskimäärin nopeampi yksinkertaisissa tulostuksissa: printf vai echo.

Siitä on ihan liian aikaista puhua mihin kaikkeen muuhun tästä on apua; ehkä vain BASH:in omituisuuksien tutkimiseen.
- saat muuten mielikuvan siitä paljonko nollasuoritus kestää eri suorituskerroilla käyttäen skriptiä:
Koodia: [Valitse]
for n in {1..20}; do alkuhetki=$(date +%s%N); : ; loppuhetki=$(date +%s%N); aika=$((10#$loppuhetki-10#$alkuhetki)); apu=000000000$aika; apu=${apu: -14: -9}.${apu: -9}; echo ${apu##+(0)}; sleep 1; done
-'sleep 1' lopusssa on tarkoitettu rauhoittamaan riehumista - joskus myös BASH kompastelee omiin lahkeisiinsa jos kovin kiirehtii.
« Viimeksi muokattu: 05.12.23 - klo:18.18 kirjoittanut petteriIII »