Ubuntu Suomen keskustelualueet

Ubuntun käyttö => Ohjelmointi, palvelimet ja muu edistyneempi käyttö => Aiheen aloitti: petteriIII - 01.01.11 - klo:23.41

Otsikko: Skriptiajuri
Kirjoitti: petteriIII - 01.01.11 - klo:23.41
Skriptiajuri on tarkoitettu skriptien tekemiseen ja tehdyistä huolehtimiseen. Skriptiajuri on silkkaa versionhallintaa: kaikki skripti-versiot, kaikki skriptien dokumentti-versiot ja skriptien kaikki tulosteet talletetaan ja ylläpidetään niistä ristiinviittauksia.

Skriptien nimillä ei ole muotovaatimuksia vaan kaikkea voi käyttää mitä näppäimistä irti saa - merkki / on kylläkin ongelmallinen sillä bash tajuaa sen tiedostonimeksi. Skriptejä ylläpidetään koti-kansion kansiossa nimeltään OMATSKRIPTIT.

Skriptiajuria on helpointa ajaa omalta kovalevyltä kun sille on ensin bootattu. Ajamiseen voi käyttää Skriptiajurille tehtyä käynnistintä joka on paras sijoittaa työpöydälle ja vielä parempi on ctrl-raahata se käynnistyspalkkiin. Skriptiajuria voi ajaa myös päätteessä käskyllä: . ~/OMATSKRIPTIT/Skriptiajuri. Skriptiajuria voi ajaa myös nautiluksella mistä hyvänsä. Yksi tapas on bootata live-CD:llä ja ajaa live-CD:n nautiluksella Skriptiajuria siitä koneesta johon on bootattu tai sitten USB-muistitikulta. Ja skriptiajurilla taas voi ajaa MidnightCommanderia jolloin on pääsy lähes kaikkialle mikä on liitetty siihen koneeseen jolta on bootattu.

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. Sillä teetpä mitä hyvänsä: painat ctrl-c vahingossa tai tahallasi, boottaat, potkit konettasi ympäri kämppää ... niin aloitettaessa skriptiajuri uudelleen se aloittaa siitä paikasta joka viimeksi toimi. 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.

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.
- backup tehdään jokaiselle muistitikulle joka on liitetty johonkin USB-porttiin mikäli siinä on kansio OMATSKRIPTIT. USB-porteissa voi olla muistitikku tai ei ja niillä voi olla kansio OMATSKRIPTIT tai ei. Backup toimii kaikille käyttäjille, eikä backupin toiminta ei riipu muistitikun nimestä, uuid:stä tai mistään. Tiedostomuodosta ei välitetä kunhan koneessta löytyy ajurit.
- 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.

Skriptejä tehtäessä ei riitä, että skriptien tekeminen on helppoa ja siihen kelpaakin moni viritelmä. Mutta ongelma ei olekaan skriptien teko sinänsä, vaan se että jokainen ongelma voidaan ratkaista ziljoonalla erilaisella tavalla ja jokaisella on omat vahvuutensa ja heikkoutensa - ja tilanteeseen sopivan menetelmän valintaan tarvitaan opastusta. Tarkoitan että melkein kaikki skriptit ovat väkisin tehtyja ja huomattavasti liian isoja ja hitaita, sillä BASH:in logiikka ei sovi normaalilla tavoilla ajatteleville.   

Skriptiajuri on tehty BASH:illa sen osoittamiseksi että BASH ei ole rajoittunut pieniin skripteihin. Jo kauan on kaiken voinut tehdä käytettävyyden kannalta mielekkäimmällä tavalla sillä skriptiajurin toiminta-nopeus on usein jo turhankin suuri.

Monet järjestelmät kehuvat, että niiden koodi on editoitavissa niillä itsellään, mutta käytännössä niitä ei voi editoida millään tavalla. Sensijaan kehitettäessä skriptiajuriin uusia ominaisuuksia sitä editoidaan poikkeuksetta itsellään.

Skriptit ovat ohjelmia parempia ennenkaikkea järjestelmän hoitamisessa sillä ne ovat lyhyitä ja niissä BASH toimii vain mitättömän ajan sillä pääosa aikaa kuluu ulkoisissa ohjelmissa. Mutta skriptausta kannattaa käyttää myös silloin kun tulevasta ohjelmasta täytyy nopeasti saada mielikuva. Syy skriptien käyttämiseen on se, että skriptit kykenevät kaikkeen samaan kuin expertitkin ja ne toimivat nopeammin ja virheettömämmin. Mutta yksi skripti kykenee vain erittäin rajoitettuun toimintaan joten skriptejä tulee olla tuhansia jo vaatimattomassakin tehtävässä. Mutta suuresta skriptijoukosta valinta on hidasta, ja valinta jo tuhannesta skriptistä on tavanomaisin keinoin hankalaa mutta skriptiajurille tuommoiset mitättömät määrät eivät tunnu mitenkään.

Skriptiajuri hallitseekin skriptejään tiedostopuussa, jossa nimien pituutta tai merkkivalikoimaa ei ole rajoitettu: mikä hyvänsä merkki kelpaa lukuunottamatta merkkiä: /
 
Skriptiajuri pitää kokoajan kirjaa siitä missä se on, joten voi rauhassa painaa ctrl-c tai peräti bootata kun tehtävä skripti villiintyy tai muuttuu hiljaiseksi.

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ä. Nämä koneesta kertovat viestit saat esiin kun heti skriptiajuri alkaessa toimimaan pyörittää hiiren rullaa. Näyttö palaa 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.
 
- kaiki mitä on joskus tehty löytyy arkistosta. Editoitaessa koodeja tai dokumentteja haetaan arkistosta editoriin myös muutamia viimeisimmistä versioista ja editoitaessa koodeja haetaan editoriin myös käytetyt kirjastot.
- editoitava tiedosto tarkistetaan mentäessä ajamaan skriptiä tai editoimaan skriptiä ja mikäli koodaus-virheitä löytyy mennään editointiin ja viedään lista käännösvirheestä omalle sivulle.
- vastaus jokaiseen skriptiajurin kysymykseen talletetaan historiatietoihin. Jokaiselle kysymykselle on oma historia joten tarvittava löytyy nopeasti. Historiatietoja voi selata nuolinäppäimillä niinkuin normaalistikin tai käyttää etsintää.
- hakuja on monia erilaisia; ja nimenomaan sellaisia hakuja jotka pystyvät löytämään skripteissä olevaa kapulakieltä - internetin hakukoneet eivät muuten pysty.
- kaikki ohjelmointi perustuu kopiointiin vaikkakaan sitä ei tajuta koska kirjastot ovat kopiointi-automaatteja.
- muutokset skriptiajuriin tai sen kirjastoihin tehdään yleensä skriptiajurissa itsessään. Ulkoisia ohjelmilla voi lisätä skriptiajuriin mitä vaan mutta poistamisessa on paljon ehtoja.
- mitään ei koskaan tuhota ellei erikseen pyydetä tuhoamaan. Jokainen tehty versio talletetaan arkistoon omalla numerollaan. Numero on kasvava. Editoitaessa esitetään muutama viimeinen versio.
- arkistoon voi myös mennä kokeilemaan mikä siellä olevista versioista toimii ajettuna parhaiten ja kopioida sen koodi tehtävän skriptin paikalle.
- myös näppäin-versiossa hiirellä on suuri merkitys: sillä valitaan editorissa näytettävä lehti ja hiiren rullalla saa esimerkiksi selattua päätettä; esimerkiksi aloitusviestit saa sillä näkyviin.

 


 
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 15.02.11 - klo:13.52
/home/käyttäjänimi/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkohiirelle

Koodia: [Valitse]
#!/bin/bash   
# Valikkohiirelle (rullahiirelle)  petteriIII 2.4.2013
# Selostus tunnetuista funktioista ja niiden parametreista:
# 1. ValitseValittavistaYksi: [otsikko [avaimet [ValitunNumero]]] . Erittely:
# otsikko=vapaata tekstiä koko toinen rivi näytöllä. Jos se on annettu sitä käytetään mutta jos ei ole niin otsikko muodostetaan automaattisesti. otsikko:sta otetaan CRC-32 muuttujaan crc ja se yksilöikin kutsujan hyvin. Ulkopuolinen ohjelma saattaa käyttää sitä.
# avaimet= merkit 38-157 rivillä 1. Valikkohiirelle ohjelmassa ne eivät ole varsinaisia avaimia, vaan lisä-otsikko
# ValitunNumero= valittuna olevan järjestysnumero.

# 2. ohjeet: kaikki ~/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio tai: Skriptiajuri, näppäinversio" ohje-kansion tiedostot viedään editoriin. Tiedostoja voi lisätä tai poistaa ja Skriptiajuri ottaa muutoksen automaattisesti huomioon.
# ohjeista ei voi esittää akrkistokappaleita editorissa. Arkistokappaleet kuitenkin tehdään paikkaan: ~/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/tiedoston nimi/monotonisesti kasvava arkistonumero

# 3. etsiä_missä_skripti_on_kun_muistaa_sen_nimestä_jotakin                 
# 4. etsiä_kysyttävää_ilmaisua_skriptien_tekstistä
# 5. etsiä_esimerkkirivejä_kuinka_jotakin_käskyä_käytetään
# 6. ajaa_valitun_skriptin

echo -e "funktiot paikasta:"${0%/OMATSKRIPTIT*}"/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkohiirelle  liitetään koodiin"

function ValitseValittavistaYksi () {
function AsetaPaate { 
RivienLuku=$(($(tput lines)-6)) # näytön riviluku. 6 on otsikon+yläpalkin viemä tila
RivinPituus=$(tput cols)        # näyttörivin merkkiluku.
echo -e 'Näyttö-funktio kirjastoa kutsuva ohjelma: ' $(basename "$0")'\nnäytön riviluku:'$RivienLuku'   rivinpituus:'$RivinPituus
# gconftool ja gnome-terminal ovat gnomessa, mate:ssa on mateconftool-2 ja mate-terminal. Seuraava on testi onko mate vai joku muu
[[ $(cat /var/lib/dpkg/status  | grep \ mate-terminal) ]] && (
apu=$(mateconftool-2 -g /apps/mate-terminal/profiles/Default/default_size_columns)
mateconftool-2 -s /apps/mate-terminal/profiles/Default/use_custom_default_size --type bool true
mateconftool-2 -s /apps/mate-terminal/profiles/Default/default_size_columns --type integer 240
mateconftool-2 -s /apps/mate-terminal/profiles/Default/default_size_rows --type integer 60     
mateconftool-2 -s /apps/mate-terminal/profiles/Default/scrollback_unlimited --type bool true # rajoittamaton vieritys 
mateconftool-2 -s /apps/gedit-2/preferences/editor/line_numbers/display_line_numbers --type bool true
[[ $apu = 240 ]] || (echo 'avaa uusi pääte ja käynnistä siinä uudelleen'; sleep 3; killall mate-terminal)
)

[[ $(cat /var/lib/dpkg/status  | grep \ gnome-terminal) ]] && (
apu=$(gconftool -g /apps/gnome-terminal/profiles/Default/default_size_columns)
gconftool -s /apps/gnome-terminal/profiles/Default/use_custom_default_size --type bool true
gconftool -s /apps/gnome-terminal/profiles/Default/default_size_columns --type integer 240 # Näyttörivin maximi pituus
gconftool -s /apps/gnome-terminal/profiles/Default/default_size_rows --type integer 60     # Näyttörivien maximi määrä
gconftool -s /apps/gnome-terminal/profiles/Default/scrollback_unlimited --type bool true
gconftool -s /apps/gedit-2/preferences/editor/line_numbers/display_line_numbers --type bool true
[[ "$apu" = 240 ]] || (echo 'avaa uusi pääte ja käynnistä siinä uudelleen'; sleep 3; killall gnome-terminal)
)
valintalukko=1 # negatiivinen logiikka, valinta on nyt mahdollista suorittaa
# avaimet=''     # ohjelma perisi muuten avaimet edelliseltä ohjelmalta
raja=112\101\116\116\101\114\105\73\73\73
}

function MuutaValittuPunaiseksi {
tput cup 2 $(($RivinPituus-95))
tput sgr0; echo "näpäytä_tästä_käyttöohjeet erikoistoimet  dokumentoi koodaa"
tput cup 0 $(($RivinPituus-45)) #; tput el tyhjää loppurivi
apu=$kanta/"$KansionNimi"/'ARKISTO/SKRIPTIT/'"${Valittavat[ValitunNumero-1]}" # dokumenttien määrää ei pitäisikään näyttää
[[ $ValitunNumero>1 ]] && Tiedostonaika="" && [[ -a $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" ]] && Tiedostonaika=$(stat --printf %y $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}"  | awk '{ print $1" "$2"  "}' | tr -d '\n')           
[[ -f $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" ]] && echo -n ${Tiedostonaika:0:16} && [[ -d $apu ]] && echo -n " Koodeja:"$(ls "$apu" | sort -g | tail -n 1) && tput el
[[ -d $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" ]] && echo "kansiossa tiedostoja:"$(ls $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" | wc -l)"          " 
[[ ${Valittavat[ValitunNumero-1]} = .edellinen_kansio. ]] && tput el
Xkoordinaatti=$(((ValitunNumero - 1 - $(((ValitunNumero - 1) / RivienLuku))) / RivienLuku)); Ykoordinaatti=$((ValitunNumero - $((RivienLuku * Xkoordinaatti -1))+3));tput cup $((Ykoordinaatti - Xkoordinaatti - 2)) $((Xkoordinaatti * SarakkeenPituus));  tput setf 4; echo "${Valittavat[ValitunNumero-1])}"
}

function MuutaKaikkiValintarivitVihreiksi {
tput cup 3 0 ; tput setf 3
cat /home/petteri/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö
}

function TulostaValittavat {
clear
rm /home/petteri/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö
tput sgr0
echo -e 'Skriptiajurin hiiriversio\n'$otsikko'\n'                     
ValittavienLuku=${#Valittavat[@]}
SarakkeidenLuku=$(($((ValittavienLuku-3))/RivienLuku+1))  # oli:SarakkeidenLuku=$(($((ValittavienLuku-2))/RivienLuku+1))
SarakkeenPituus=$((RivinPituus/SarakkeidenLuku))
tput setf 3
for (( Rivi=0; Rivi<=RivienLuku; Rivi++ )) # -1 ei vissiin onnistunut
do
  for (( Sarake=0; Sarake<=SarakkeidenLuku-1; Sarake++ ))   
  do
    naytettava=${Valittavat[Sarake*RivienLuku+Sarake+Rivi]}"                                                                                                  "
    nayttoRivi="$nayttoRivi"${naytettava:0:$SarakkeenPituus}  # mitä sarakkeita näyttörivillä ennestään onkin ja uusi sarake lisää
  done
  echo "${nayttoRivi}"; echo -e "${nayttoRivi}" >> /home/petteri/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö; naytto[$Rivi]=${nayttoRivi:0:$RivinPituus}; nayttoRivi='' 
done 
}

function MuutaValittuNuolinappaimilla {
MuutaValittuPunaiseksi
 echo -en "\e[?1000h"; read -n6 -s -t0.02 key ; echo -en "\e[?1001h"
stty -echo
[[ ${key:3:1} = "a" ]] && MuutaValittua -1  # rullaus ylös
[[ ${key:3:1} = "\`" ]] && MuutaValittua 1  # rullaus alas
if [[ ${key:3:1} = "#" ]]; then valintatehty=1; x=$(LC_CTYPE=C printf '%d' "'${key:4:1}"); y=$(LC_CTYPE=C printf '%d' "'${key:5:1}")
  [[ $y = 33 ]] && [[ $x < 40 ]] && Tapahtuma=palaa && valintatehty=1 && return
  [[ $y = 33 ]] && [[ $x < 70 ]] && Tapahtuma=uusi && valintatehty=1 && return
  [[ $y = 35 ]] && [[ $x > $(($RivinPituus-10)) ]] && Tapahtuma=koodaa && valintatehty=1 && return
  [[ $y = 35 ]] && [[ $x > $(($RivinPituus-18)) ]] && Tapahtuma=dokumentoi && valintatehty=1 && return
  [[ $y = 35 ]] && [[ $x > $(($RivinPituus-36)) ]] && Tapahtuma=erikoistoimet && valintatehty=1 && return
  [[ $y = 35 ]] && [[ $x > $(($RivinPituus-57)) ]] && Tapahtuma=käyttöohjeet && valintatehty=1 && return
  [[ $y > 35 ]] && MuutaKaikkiValintarivitVihreiksi && ValitunNumero=$((y-34+(((RivienLuku+1)*((x-34)/SarakkeenPituus)))-1)) && MuutaValittuPunaiseksi && return
valintatehty=0
fi                                                         
}

function MuutaValittua () {
MuutaKaikkiValintarivitVihreiksi
ValitunNumero=$(($ValitunNumero+$1))
[[ $ValitunNumero -lt 1 ]] && TulostaValittavat && ValitunNumero=1 # TulostaValittavat lisätty
[[ $ValitunNumero -gt $ValittavienLuku ]] && ValitunNumero=$ValittavienLuku # apu->ValittavienLuku; -2 lisätty poistettu
}
 
# function ValitseValittavistaYksi () {
[[ $3 ]] && ValitunNumero=$3
[[ ${#Valittavat} == 0 ]] && echo 'ei ole valittavaa' && sleep 2 && valintatehty=1 && break
AsetaPaate
local otsikko key valintatehty=0 Xkoordinaatti Ykoordinaatti   
[[ ! $ValitunNumero || $ValitunNumero -lt 1 || $ValitunNumero -gt ${#Valittavat[@]} ]] && ValitunNumero=1
setterm -cursor off 
otsikko="$1"; [[ ! "$otsikko" ]] && otsikko='Ohjelma: '$0' pyytää valitsemaan näistä'
crc=$(echo $otsikko | cksum | awk {'print $1'}) # cksum=32bittinen crc, sha1sum ->160bittinen ...
TulostaValittavat
valintatehty=0
Tapahtuma=""
while [ $valintatehty -lt 1 ] ; do MuutaValittuNuolinappaimilla;  done
clear; tput sgr0; stty echo # setterm -reset # värit normaaleiksi # clear lisätty
ValitunTeksti=${Valittavat[ValitunNumero-1]}
[[ ! ${ValitunArvo[ValitunNumero-1]} ]] && ValitunArvo='ei määritelty' || ValitunArvo=${ValitunArvo[ValitunNumero-1]}
}

# loput funktiot ovat Skriptiajuri:n hiiriversiota varten eivätkä sotke mitään. Näppäinversiossa paremmat funktiot?
function etsiä_missä_skripti_on_kun_muistaa_sen_nimestä_jotakin () {
avaimet='palaa Skriptiajuri:en        uusi hakutermi'
while true
do
  clear; cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/grepin_määreet; echo; echo
  lue_näppäimistöltä hakusana "mitä ilmausta etsit kansioiden tai skriptien nimistä (teksti voi olla keskelläkin sanaa)?"
  eval Valittavat=(" "$(find /home/petteri/OMATSKRIPTIT |  grep "$hakusana" | grep -v /ARKISTO/ | grep -v *sgml | sed 's/^ */"/g;s/ *$/"/g'))
  ValitunNumero=$(cat $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2)
  ValitseValittavistaYksi "ilmaus löytyi näiden skriptien nimistä: tutki valittu painamalla enter sen kohdalla" "$avaimet"
  [[ $Tapahtuma = "palaa" ]] && break
  [[ $Tapahtuma = "uusi" ]] ||  echo 'editoin tiedostoa: '/home/petteri/OMATSKRIPTIT/palautuspiste "$ValitunTeksti" && gedit "$ValitunTeksti" && break
done
echo $ValitunNumero > $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2
}

function etsiä_kysyttävää_ilmaisua_skriptien_tekstistä {
kansio_josta_ei_haeta='\/ARKISTO\/'
clear; cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/grepin_määreet; echo; echo ; echo
lue_näppäimistöltä hakusana "mitä ilmausta etsit kaikista omista skripteistä ?"
optiot="-lr" 
apu=${hakusana%% *}
[[ ${hakusana:0:1} = "-" ]] && optiot="-lr"${apu:1} && hakusana=${hakusana#* }
[[ $(echo $hakusana | grep ^man) ]] && $hakusana > ${hakusana:4} && gedit ${hakusana:4} haku=CTRL-f && rm ${hakusana:4} && return
eval Valittavat=($(grep $optiot "$hakusana" $kanta/OMATSKRIPTIT | grep -v $kansio_josta_ei_haeta | grep -v kopio | sed 's/\/home\/petteri\/OMATSKRIPTIT\///g' | sed 's/^ */"/g;s/ *$/"/g'  ))
[[ -f $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2 ]] && ValitunNumero=$(cat $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2)
while true
do
  avaimet='palaa Skriptiajuri:een  uusi hakutermi' # end=palaa Skriptiajuri:en   f2=anna uusi hakutermi
  ValitseValittavistaYksi "ilmaus löytyi näistä skripteistä: valitse editoitava valitsemalla se ja painamalla enter" "$avaimet" 
  [[ $Tapahtuma = "palaa" ]] && break
  [[ $Tapahtuma = "uusi" ]] && etsiä_kysyttävää_ilmaisua_skriptien_tekstistä
  gedit /home/$(whoami)/OMATSKRIPTIT/"$ValitunTeksti"
done
echo $ValitunNumero > $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2
}

function etsiä_esimerkkirivejä_kuinka_jotakin_käskyä_käytetään { # lisätty
clear; cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/grepin_määreet; echo; echo
lue_näppäimistöltä hakusana "millaisia esimerkkirivejä etsit kaikista omista skripteistä ?"
find ~/OMATSKRIPTIT ! -path '*ARKISTO*' ! -path *sgml -type f  -exec grep "$hakusana" {} \;
read -p 'hiirellä voi vieritää näyttöä. paina enter jatkaakseesi'
}

function ohjeet { # home. kaikkia ohjekansion tiedostoja tarjotaan editoitaviksi. Tiedostoja voi lisätä tai poistaa ja Skriptiajuri ottaa muutoksen automaattisesti huomioon.
# paikassa: $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, hiiriversio"/<tiedoston nimi>/<monotonisesti kasvava arkistonumero> on kopio kaikista muuttuneista tiedostoista
gedit & # tämä käsky aiheuttaa sen että pääohjelma ei pysähdy tuleviin gedit-käskyihin vaan jatkaa taustalla ilman näppäimiä ja fyysistä näyttöä
täytä_valittavat $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio"
for (( n=2; n<=${#Valittavat[@]}-1; n++ )); do 
TiedostonAikaleimaAlussa[$n]=$(stat --printf %y $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}" | awk '{ print $2 }')
gedit $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}"
done
reset; read -p 'paina enter'
# sen varalta että joku ohje on muuttunut lisätään sen kopio arkistoon. Samalla poistuvat nollatut:
täytä_valittavat $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio"
for (( n=2; n<=${#Valittavat[@]}-1; n++ )); do
  [[ ! -d $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}" ]] && mkdir -p $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}" && touch $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}"/0
  [[ ${TiedostonAikaleimaAlussa[$n]} = $(stat --printf %y $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}" | awk '{ print $2 }' ) ]] && continue
  Suurin_numero_ohjeissa=$(ls $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}" | sort -g | tail -n 1)
  cp $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}"  $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, hiiriversio"/"${Valittavat[$n]}"/$(($Suurin_numero_ohjeissa+1))
done
}

function ajaa_valitun_skriptin {
[[ $ValitunTeksti = '.edellinen_kansio.' ]] && KansionNimi=$(dirname "$KansionNimi") && echo "$KansionNimi">$kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/KansionNimiAloituksessa && HaeSenRinvinNumeroJollaViimeksiTyöskenneltiinTässäKansiossa "$KansionNimi" && return
[[ -d $kanta/"$KansionNimi"/"$ValitunTeksti" ]] && KansionNimi="$KansionNimi"/"$ValitunTeksti" && return
[[ $(echo "$ValitunTeksti" | grep -e '.PDF' -e '.pdf') ]] && evince $kanta/"$KansionNimi"/"$ValitunTeksti" && return # html:lle myös
[[ $(echo "$ValitunTeksti" | grep -e '\.doc' -e .html -e .odt -e .sgml -e .xml) ]] && /usr/bin/libreoffice $kanta/"$KansionNimi"/"$ValitunTeksti" && return
[[ ! -d $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti" ]] && mkdir -p $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti" #?
bash -n $kanta/"$KansionNimi"/"$ValitunTeksti" &>$kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
[[ ! -f $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe ]] && echo "" > $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
[[ $(cat -b $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe) > 0 ]] && echo 'tulkkauskelvoton, mennään koodaamaan' && sleep 0.2 && koodaa && return
[[ $(cat $kanta/"$KansionNimi"/"$ValitunTeksti" | grep \$1) ]] && LueParametrit # jos skriptissä on viittauksia parametreihin käydään lukemassa niitä
clear && echo -e 'suoritan skriptin: '$kanta/"$KansionNimi"/$ValitunTeksti'\n' && bash $kanta/"$KansionNimi"/"$ValitunTeksti" $Parametrit && read -p 'jatkaakseesi paina enter' || ( reset; echo "skriptisi päätyi virheeseen virhe-statuksella: "$? ; read -p "jatkaakseesi paina enter"; /home/petteri/OMATSKRIPTIT/"Skriptiajuri, hiiriversio" )
}
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 01.03.11 - klo:08.04
~/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkonäppäimille

Koodia: [Valitse]
#!/usr/bin/env bash   
# valikkonäppäimille  petteriIII 2.4.2013
# Selostus tunnetuista funktioista ja niiden parametreista:
# 1. ValitseValittavistaYksi: [otsikko [avaimet [ValitunNumero]]] . Erittely:
# otsikko=vapaata tekstiä koko toinen rivi näytöllä. Jos se on annettu sitä käytetään mutta jos ei ole niin otsikko muodostetaan automaattisesti. otsikko:sta otetaan CRC-32 muuttujaan crc ja se yksilöikin kutsujan hyvin. Ulkopuolinen ohjelma saattaa käyttää sitä.
# avaimet= merkit 38-157 rivillä 1. Tämä on tekstiä jossa esiintyy mahdollisten avaimien nimet (f1-f4, home, end, insert ja delete). Kannatta selventää kirjoittamalla mitä mikin tekee: f2=<mitä se tekee> insert=<mitä se tekee> ...   avaimet joiden nimeä ei ole mainittu eivät toimi
# ValitunNumero= valittuna olevan järjestysnumero.

# 2. ohjeet: kaikki ~/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio tai: Skriptiajuri, näppäinversio" ohje-kansion tiedostot viedään editoriin. Tiedostoja voi lisätä tai poistaa ja Skriptiajuri ottaa muutoksen automaattisesti huomioon. Tyhjäämällä ohjesivun se tuhotaan kun editorista poistutaan.
# ohjeista ei voi esittää arkistokappaleita editorissa. Arkistokappaleet kuitenkin tehdään paikkaan: ~/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/tiedoston nimi/monotonisesti kasvava arkistonumero

# 3. etsiä_missä_skripti_on_kun_muistaa_sen_nimestä_jotakin                 
# 4. etsiä_kysyttävää_ilmaisua_skriptien_tekstistä
# 5. etsiä_esimerkkirivejä_kuinka_jotakin_käskyä_käytetään
# 6. ajaa_valitun_skriptin
 

function ValitseValittavistaYksi () {                   
function AsetaPaate () {  # yritetään tehdä päätteen ja geditin asetukset
RivienLuku=$(($(tput lines)-6)) # näytön riviluku. 6 on otsikon+yläpalkin viemä tila
RivinPituus=$(tput cols)        # näyttörivin merkkiluku.
echo -e 'Näyttö-funktio kirjastoa kutsuva ohjelma: ' $(basename "$0")'\nnäytön riviluku:'$RivienLuku'   rivinpituus:'$RivinPituus
# gconftool ja gnome-terminal ovat gnomessa, mate:ssa on mateconftool-2 ja mate-terminal.
[[ $(cat /var/lib/dpkg/status  | grep \ mate-terminal) ]] && (
apu=$(mateconftool-2 -g /apps/mate-terminal/profiles/Default/default_size_columns)
mateconftool-2 -s /apps/mate-terminal/profiles/Default/use_custom_default_size --type bool true
mateconftool-2 -s /apps/mate-terminal/profiles/Default/default_size_columns --type integer 240
mateconftool-2 -s /apps/mate-terminal/profiles/Default/default_size_rows --type integer 60     
mateconftool-2 -s /apps/mate-terminal/profiles/Default/scrollback_unlimited --type bool true # rajoittamaton vieritys 
mateconftool-2 -s /apps/gedit-2/preferences/editor/line_numbers/display_line_numbers --type bool true
[[ $apu = 240 ]] || (echo 'avaa uusi pääte ja käynnistä siinä uudelleen'; sleep 3; killall mate-terminal)
)

[[ $(cat /var/lib/dpkg/status  | grep \ gnome-terminal) ]] && (
apu=$(gconftool -g /apps/gnome-terminal/profiles/Default/default_size_columns)
gconftool -s /apps/gnome-terminal/profiles/Default/use_custom_default_size --type bool true
gconftool -s /apps/gnome-terminal/profiles/Default/default_size_columns --type integer 240 # Näyttörivin maximi pituus
gconftool -s /apps/gnome-terminal/profiles/Default/default_size_rows --type integer 60     # Näyttörivien maximi määrä
gconftool -s /apps/gnome-terminal/profiles/Default/scrollback_unlimited --type bool true
gconftool -s /apps/gedit-2/preferences/editor/line_numbers/display_line_numbers --type bool true
[[ "$apu" = 240 ]] || (echo 'avaa uusi pääte ja käynnistä siinä uudelleen'; sleep 3; killall gnome-terminal)
)
valintalukko=1 # negatiivinen logiikka, valinta on nyt mahdollista suorittaa
raja=112\101\116\116\101\114\105\73\73\73
}

function MuutaValittuPunaiseksi () {
tput sgr0 # värit normaaleiksi
tput cup 0 $(($RivinPituus-42)); tput el # kursorin asettaminen ja loppurivin tyhjääminen
apu=$kanta/"$KansionNimi"/'ARKISTO/SKRIPTIT/'"${Valittavat[ValitunNumero-1]}" # dokumenttien määrää ei pitäisikään näyttää
[[ -f $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" ]] && Tiedostonaika=$(stat --printf %y $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}"  | awk '{ print $1" "$2"  "}' | tr -d '\n') && echo -n ${Tiedostonaika:0:16} && [[ -d $apu ]] && echo -n " Koodi:"$(ls "$apu" | sort -g | tail -n 1)" " 
[[ -d $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" ]] && echo "kansiossa tiedostoja:"$(ls $kanta/"$KansionNimi"/"${Valittavat[ValitunNumero-1]}" | wc -l) 
Xkoordinaatti=$(((ValitunNumero - 1 - $(((ValitunNumero - 1) / RivienLuku))) / RivienLuku)); Ykoordinaatti=$((ValitunNumero - $((RivienLuku * Xkoordinaatti -1))+3));tput cup $((Ykoordinaatti - Xkoordinaatti - 2)) $((Xkoordinaatti * SarakkeenPituus));  tput setf 4; echo "${Valittavat[ValitunNumero-1])}"
}

function MuutaKaikkiValintarivitVihreiksi () {
tput cup 3 0 ; tput setf 3
cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö
}

function TulostaOtsikot () {
clear
tput sgr0
[[ $valintalukko = 1 ]] && echo -n 'enter=valitse tämä   ' || echo -n 'paina nuoliylös-alas  '
echo -e "$avaimet"'\n'$otsikko'\n' 
}

function TulostaValittavat () {
TulostaOtsikot
rm $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö                     
# ValittavienLuku=${#Valittavat[@]}
SarakkeidenLuku=$(($((ValittavienLuku-3))/RivienLuku+1))  # oli: SarakkeidenLuku=$(($((ValittavienLuku-2))/RivienLuku+1))
SarakkeenPituus=$((RivinPituus/SarakkeidenLuku))
tput setf 3
for (( Rivi=0; Rivi<=RivienLuku; Rivi++ ))
do
  for (( Sarake=0; Sarake<=SarakkeidenLuku-1; Sarake++ ))   
  do
    naytettava=${Valittavat[Sarake*RivienLuku+Sarake+Rivi]}"                                                                                                  "
    nayttoRivi="$nayttoRivi"${naytettava:0:$SarakkeenPituus}  # mitä sarakkeita näyttörivillä ennestään onkin ja uusi sarake lisää
  done
  echo "${nayttoRivi}"; echo -e "${nayttoRivi}" >> $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö; nayttoRivi='' 
done 
}

function MuutaValittuNuolinappaimilla () {
MuutaValittuPunaiseksi
read -sn 1 key
stty -echo
[[ -z $key ]] && Tapahtuma='enter' && valintatehty=$valintalukko && valintalukko=0 && return  # enter
set +e
[[ ! ${key#*[PQRSHF23]} ]] && Tapahtuma=${avain[$key]} && valintatehty=${valintasallittu[$key]} # f1,f2,f3,f4,home,end,insert tai delete
[[ ! ${key#*[ABCD]} ]] && MuutaKaikkiValintarivitVihreiksi && tput cup 0,0 && echo -n 'enter=valitse tämä   ' && valintalukko=1 && ${avain[$key]} # nuolinäppäimet
read -sn1 -t .001 key # tuntuu auttavan
set -e
}

function MuutaValittua () {
ValitunNumero=$(($ValitunNumero+$1))
[[ $ValitunNumero -lt 1 ]] && ValitunNumero=1
apu=${#Valittavat[*]}
[[ $ValitunNumero -gt $apu ]] && ValitunNumero=$apu
}
 
# function ValitseValittavistaYksi () {
ValittavienLuku=${#Valittavat[@]}; [[ $ValittavienLuku = 0 ]] && echo "ei valittavia" && Tapahtuma="end" && sleep 2 && return
AsetaPaate
[[ $3 ]] && ValitunNumero=$3 # valintalukko=1 # mikäli on annettu kolme parametria niin entereitä voi kerätä varastoon
avaimet=$2
declare -A valintasallittu avain
avain['A']='MuutaValittua -1' 
avain['B']='MuutaValittua 1'
avain['C']='MuutaValittua '$((RivienLuku+1))
avain['D']='MuutaValittua -'$((RivienLuku+1))
[[ ! $(echo $avaimet | grep f1) ]] && valintasallittu['P']=0 || valintasallittu['P']=1 && avain['P']='f1'
[[ ! $(echo $avaimet | grep f2) ]] && valintasallittu['Q']=0 || valintasallittu['Q']=1 && avain['Q']='f2'
[[ ! $(echo $avaimet | grep f3) ]] && valintasallittu['R']=0 || valintasallittu['R']=1 && avain['R']='f3'
[[ ! $(echo $avaimet | grep f4) ]] && valintasallittu['S']=0 || valintasallittu['S']=1 && avain['S']='f4'
[[ ! $(echo $avaimet | grep home) ]] && valintasallittu['H']=0 || valintasallittu['H']=1 && avain['H']='home'
[[ ! $(echo $avaimet | grep end) ]] && valintasallittu['F']=0 || valintasallittu['F']=1  && avain['F']='end'
[[ ! $(echo $avaimet | grep insert) ]] && valintasallittu['2']=0 || valintasallittu['2']=1 && avain['2']='insert' 
[[ ! $(echo $avaimet | grep delete) ]] && valintasallittu['3']=0 || valintasallittu['3']=1 && avain['3']='delete'
local otsikko key valintatehty=0 Xkoordinaatti Ykoordinaatti   
[[ ! $ValitunNumero || $ValitunNumero -lt 1 || $ValitunNumero -gt ${#Valittavat[@]} ]] && ValitunNumero=1
setterm -cursor off 
otsikko="$1"; [[ ! "$otsikko" ]] && otsikko='Ohjelma: '$0' pyytää valitsemaan näistä'
crc=$(echo $otsikko | cksum | awk {'print $1'}) # cksum=32bittinen crc, sha1sum ->160bittinen ...
TulostaValittavat
valintatehty=0
Tapahtuma=''
while [ $valintatehty -lt 1 ] ; do MuutaValittuNuolinappaimilla;  done
clear; tput sgr0; setterm -reset; stty echo # clear lisätty
ValitunTeksti=${Valittavat[ValitunNumero-1]}
[[ $ValitunTeksti = '.edellinen kansio.' ]] && valintalukko=1
[[ ! ${ValitunArvo[ValitunNumero-1]} ]] && ValitunArvo='ei määritelty' || ValitunArvo=${ValitunArvo[ValitunNumero-1]}
}

# loput funktiot ovat Skriptiajuria varten
function etsiä_missä_skripti_on_kun_muistaa_sen_nimestä_jotakin () {
avaimet='end=palaa Skriptiajuriin        f2=uusi hakutermi'
while true
do
  clear; cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/grepin_määreet; echo; echo
  lue_näppäimistöltä hakusana "mitä ilmausta etsit kansioiden tai skriptien nimistä (teksti voi olla keskelläkin sanaa)?"
  eval Valittavat=(" "$(find $kanta/OMATSKRIPTIT |  grep  "$hakusana" | grep -v /ARKISTO/ | grep -v *sgml | sed 's/^ */"/g;s/ *$/"/g'))
  ValitunNumero=$(cat $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2)
  ValitseValittavistaYksi "ilmaus löytyi näiden skriptien nimistä: valitse editoitava näpäyttämällä sitä hiiriosoittimella." "$avaimet"
  [[ $Tapahtuma = "end" ]] && break
  [[ $Tapahtuma = "f2" ]] ||  echo 'editoin tiedostoa: '$kanta/OMATSKRIPTIT/palautuspiste "$ValitunTeksti" && gedit "$ValitunTeksti" && break
done
echo $ValitunNumero > $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2
}

function etsiä_kysyttävää_ilmaisua_skriptien_tekstistä { # etsi_näistä, -v ?
clear; cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/grepin_määreet; echo
lue_näppäimistöltä hakusana "mitä ilmausta etsit kaikista omista skripteistä ?"
optiot="-lr"; [[ ${hakusana:0:3} = '-i ' ]]  && optiot=${hakusana%% *}lr && hakusana=${hakusana#* }
[[ ${hakusana:0:3} = '-E ' ]]  && optiot=${hakusana%% *}lr && hakusana=${hakusana#* }
eval Valittavat=($(grep $optiot "$hakusana" $kanta/OMATSKRIPTIT | grep -v /ARKISTO/ | grep -v kopio | sed 's/^ */"/g;s/ *$/"/g'  ))
for (( n=0; n<=${#Valittavat[@]}-1 ; n++ )); do Valittavat[$n]=${Valittavat[$n]##*OMATSKRIPTIT\/}; done
[[ -f $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2 ]] && ValitunNumero=$(cat $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2)
while true
do
  avaimet='end=palaa Skriptiajuriin  f2=uusi hakutermi'
  ValitseValittavistaYksi "ilmaus löytyi näistä skripteistä: valitse editoitava nuolinäppäimillä ja paina enter" "$avaimet" 
  [[ $Tapahtuma = "end" ]] && break
  [[ $Tapahtuma = "f2" ]] && etsiä_kysyttävää_ilmaisua_skriptien_tekstistä
  gedit  $kanta/OMATSKRIPTIT/"$ValitunTeksti"
done
echo $ValitunNumero > $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku2
}

function etsiä_esimerkkirivejä_kuinka_jotakin_käskyä_käytetään {
clear; cat $kanta/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/grepin_määreet; echo; echo
lue_näppäimistöltä hakusana "millaisia esimerkkirivejä etsit kaikista omista skripteistä ?"
find ~/OMATSKRIPTIT ! -path '*ARKISTO*' ! -path *sgml -type f  -exec grep "$hakusana" {} \;
read -p 'hiirellä voi vieritää näyttöä. paina enter jatkaakseesi'
}

function ohjeet { # home. kaikkia ohjekansion tiedostoja tarjotaan editoitaviksi. Tiedostoja voi lisätä tai poistaa ja Skriptiajuri ottaa muutoksen automaattisesti huomioon.
# paikassa: $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, näppäinversio"/<tiedoston nimi>/<monotonisesti kasvava arkistonumero> on kopio kaikista muuttuneista tiedostoista
gedit & # tämä käsky aiheuttaa sen että pääohjelma ei pysähdy tuleviin gedit-käskyihin vaan jatkaa taustalla ilman näppäimiä ja fyysistä näyttöä
täytä_valittavat $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio"
for (( n=2; n<=${#Valittavat[@]}-1; n++ )); do 
TiedostonAikaleimaAlussa[$n]=$(stat --printf %y $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}" | awk '{ print $2 }')
gedit $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}"
done
reset; read -p 'paina enter'
# sen varalta että joku ohje on muuttunut lisätään sen kopio arkistoon. Samalla poistuvat tyhjätyt ohjeet
täytä_valittavat $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio"
for (( n=2; n<=${#Valittavat[@]}-1; n++ )); do
  [[ ! -d $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}" ]] && mkdir -p $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}" && touch $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}"/0
  [[ ${TiedostonAikaleimaAlussa[$n]} = $(stat --printf %y $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}" | awk '{ print $2 }' ) ]] && continue
  Suurin_numero_ohjeissa=$(ls $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}" | sort -g | tail -n 1)
  cp $kanta/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}"  $kanta/OMATSKRIPTIT/OHJEITA/ARKISTO/SKRIPTIT/"Skriptiajuri, näppäinversio"/"${Valittavat[$n]}"/$(($Suurin_numero_ohjeissa+1))
done
}

function ajaa_valitun_skriptin {
# [[ $ValitunTeksti = '.edellinen_kansio.' ]] && KansionNimi=$(dirname "$KansionNimi") && echo "$KansionNimi">$kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/KansionNimiAloituksessa && HaeSenRinvinNumeroJollaViimeksiTyöskenneltiinTässäKansiossa "$KansionNimi" && return
[[ -d $kanta/"$KansionNimi"/"$ValitunTeksti" ]] && KansionNimi="$KansionNimi"/"$ValitunTeksti" && return
[[ $(echo "$ValitunTeksti" | grep -e '.PDF' -e '.pdf') ]] && evince $kanta/"$KansionNimi"/"$ValitunTeksti" && return
[[ $(echo "$ValitunTeksti" | grep -e '\.doc' -e .html -e .odt -e .sgml -e .xml) ]] && /usr/bin/libreoffice $kanta/"$KansionNimi"/"$ValitunTeksti" && return
# [[ ! -d $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti" ]] && mkdir -p $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"
bash -n $kanta/"$KansionNimi"/"$ValitunTeksti" &>$kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
[[ ! -f $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe ]] && echo "" > $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
[[ $(cat -b $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe) > 0 ]] && echo 'tulkkauskelvoton, mennään koodaamaan' && sleep 0.5 && koodaa && return
[[ $(cat $kanta/"$KansionNimi"/"$ValitunTeksti" | grep \$1) ]] && LueParametrit # jos skriptissä on viittauksia parametreihin käydään lukemassa niitä
clear && echo -e 'suoritan skriptin: '$kanta/"$KansionNimi"/$ValitunTeksti'\n' && time bash $kanta/"$KansionNimi"/"$ValitunTeksti" $Parametrit && read -p 'jatkaakseesi paina enter' || ( reset; echo "skriptisi päätyi virheeseen virhe-statuksella: "$? ; read -p "jatkaakseesi paina enter"; $kanta/OMATSKRIPTIT/"Skriptiajuri, näppäinversio" )
}
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 11.04.11 - klo:18.55
liitä koodi tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot1

IDE1funktiot ja IDE2funktiot tarjoavat skriptiajurille sen tarvitsemat funktiot.

Koodia: [Valitse]
#!/bin/bash  
# petteriIII 2.4.2013 # trap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 notify-send -hint?????  xmessage
echo -e "funktiot paikasta:"${0%/OMATSKRIPTIT*}"/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot1 liitetään koodiin"

function tehdä_uuden_skriptin_tähän_kansioon () {
while true; do
  lue_näppäimistöltä SkriptinNimi "mikä tulee uuden skriptin nimeksi: "
  [[ ! -f $kanta/"$KansionNimi"/"$SkriptinNimi" ]] && break || echo 'sen niminen on jo' && sleep 2
done
etsi_samannimiset_skriptit "$SkriptinNimi"
[[ ! $SkriptinNimi ]] && return
echo -e '#!/bin/bash'>$kanta/"$KansionNimi"/"$SkriptinNimi"
gedit $kanta/"$KansionNimi"/"$SkriptinNimi"
muuta_uusi_nimi_valituksi
}

function etsi_samannimiset_skriptit () {
avaimet="end=palaa Skriptiajuriin jatkamaan skriptintekoa           home=peru skriptinteko"
hakusana="$1"
ValitunNumero=1
eval Valittavat=(" "$(find $kanta/OMATSKRIPTIT |  grep  "$hakusana" | grep -v /ARKISTO/ | grep -v *sgml | sed 's/^ */"/g;s/ *$/"/g'))
while true
do  
  [[ ! ${Valittavat[0]} ]] && break
  ValitseValittavistaYksi "näillä skripteillä on samankaltainen nimi: katso enteriä painamalla onko joku samanlainen kuin se minkä aiot tehdä" "$avaimet"
  [[ $Tapahtuma = "end" ]] && break
  [[ $Tapahtuma = "home" ]] && SkriptinNimi="" && return
  gedit "$ValitunTeksti"
  let ValitunNumero++
done
}

function rajoittaa_tämän_skriptin_arkistossa_koodien_lukua {
for apu in SKRIPTIT # dokumentteja tuskin kertyy rajoitettavaksi
do
  echo -n 'ARKISTO/'$apu/"$ValitunTeksti"' tilatarve sanoja: '; (echo 0; find $kanta/"$KansionNimi"/ARKISTO/$apu/"$ValitunTeksti" -printf '%s +\n'; echo p) | dc
  Suurin_numero=$(($(ls --ignore=*'_dokumentti' $kanta/"$KansionNimi"/ARKISTO/$apu/"$ValitunTeksti" | sort -g | tail -n 1)-10))
  Pienin_numero=$(ls --ignore=*'_dokumentti' --ignore=ARKISTO $kanta/"$KansionNimi"/ARKISTO/$apu/"$ValitunTeksti" | sort -g | head -n 1)
  [[ Suurin_numero-Pienin_numero -gt 99 ]] && echo $apu'  ARKISTO-kopioiden lukumäärä: '$((Suurin_numero-Pienin_numero))'  vähennetään 99:ään' || echo 'ei vähennettävää'
  for (( n=Pienin_numero; n<=Suurin_numero-99; n++ ));do
    [[ -f $kanta/"$KansionNimi"/ARKISTO/$apu/"$ValitunTeksti"/$n ]] && rm $kanta/"$KansionNimi"/ARKISTO/$apu/"$ValitunTeksti"/$n
  done
done
read -p 'paina enter jatkaakseesi'
}

function tehdä_uuden_kansion_tähän_kansioon () {
lue_näppäimistöltä UusiKansio "mikä tulee uuden kansion nimeksi: "
UusiKansio=$(echo "$UusiKansio" | tr [:lower:] [:upper:])
echo 'Luon kansiot nimeltä: '$kanta/"$KansionNimi"/"$UusiKansio"' ja sille arkistot'
mkdir -p $kanta/"$KansionNimi"/"$UusiKansio"/ARKISTO/{SKRIPTIT,DOKUMENTIT,HISTORIAT,POISTETUT}
echo 1 > $kanta/"$KansionNimi"/"$UusiKansio"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa
}

function poistaa_tämän_valitun_kohdan () {
echo 'siirrän: '$kanta/"$KansionNimi"/"$ValitunTeksti"'  POISTETTUIHIN. Sieltä se löytyy jos haluat takaisin'
[[ ! -d $kanta/"$KansionNimi"/ARKISTO/POISTETUT ]] && mkdir $kanta/"$KansionNimi"/ARKISTO/POISTETUT
mv $kanta/"$KansionNimi"/"$ValitunTeksti" $kanta/"$KansionNimi"/ARKISTO/POISTETUT/"$ValitunTeksti"
# rm -R $kanta/"$KansionNimi"/ARKISTO/{SKRIPTIT,DOKUMENTIT,HISTORIAT}/"$ValitunTeksti"  
sleep 1
}

function muuttaa_tämän_kohdan_nimeä () {
SkriptinNimi="$ValitunTeksti"
lue_näppäimistöltä  SkriptinNimi 'Nimeämisen voi tehdä ainoastaan samaan kansioon. Nimi on nyt: '"$ValitunTeksti""\nmiksi haluat muuttaa sen: "
mv $kanta/"$KansionNimi"/"$ValitunTeksti" $kanta/"$KansionNimi"/"$SkriptinNimi"
[[ -f $kanta/"$KansionNimi"/"$SkriptinNimi" ]] && ( # tiedostosta kyseenollen arkistot uudellen-nimetään myös # rivi lisätty; kokeile toiminta ja poista kommentti
mv $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti" $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$SkriptinNimi"
mv $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$ValitunTeksti"_dokumentti $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$SkriptinNimi"_dokumentti
mv $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti" $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$SkriptinNimi"
mv $kanta/"$KansionNimi"/ARKISTO/HISTORIAT/"$ValitunTeksti" $kanta/"$KansionNimi"/ARKISTO/HISTORIAT/"$SkriptinNimi" )
muuta_uusi_nimi_valituksi
}

function siirtää_osoitettavaan_kansioon_osoitettavat_kansiot_tai_skriptit () {  
KansioJohonSiirretaan="OMATSKRIPTIT"
avaimet="valitse kansio johon siirretään ja paina f3 kun olet siinä kansiossa     f2=palaa Skriptiajuriin"
while true
do  
  täytä_valittavat "$KansioJohonSiirretaan"
  ValitseValittavistaYksi "Nyt ollaan kansiossa: ""$KansionNimi" "$avaimet" 1 valinta
  [[ $Tapahtuma = f3 ]] && break
  [[ $Tapahtuma = f2 ]] && return
  [[ $ValitunTeksti = ".edellinen_kansio." ]] && KansioJohonSiirretaan=$(dirname "$KansioJohonSiirretaan") && KansionNimi="$KansioJohonSiirretaan"
  [[ -d "$KansioJohonSiirretaan"/"$ValitunTeksti" ]] && KansioJohonSiirretaan="$KansioJohonSiirretaan"/"$ValitunTeksti" && KansionNimi="$KansioJohonSiirretaan"
done
KansionNimi='OMATSKRIPTIT'
avaimet="f3=lopeta  f4=siirrä tämä"
while true
do
  täytä_valittavat $kanta/"$KansionNimi"
  ValitseValittavistaYksi "Valittu siirretään painettaessa f4 kansioon:""$KansioJohonSiirretaan" "$avaimet"
  [[ $ValitunTeksti = '.edellinen kansio.' ]] && KansionNimi=$(dirname "$KansionNimi") && continue
  [[ $Tapahtuma = f3 ]] && return
  [[ $Tapahtuma = 'enter' ]] && [[ -d $kanta/"$KansionNimi"/"$ValitunTeksti" ]] && KansionNimi=/"$KansionNimi"/"$ValitunTeksti"
  [[ $Tapahtuma = f4 ]] && {
  [[ -d $kanta/"$KansionNimi"/"$ValitunTeksti" ]] &&  mv -u $kanta/"$KansionNimi"/"$ValitunTeksti"  "$KansioJohonSiirretaan"/"$ValitunTeksti" && continue
    mv -u $kanta/"$KansionNimi"/"$ValitunTeksti"  "$KansioJohonSiirretaan"/"$ValitunTeksti"
    mv -u $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"  "$KansioJohonSiirretaan"/ARKISTO/SKRIPTIT/"$ValitunTeksti" # tiedostosta kyseenollen arkistot siirretään myös
    mv -u $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"  "$KansioJohonSiirretaan"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"
    mv -u $kanta/"$KansionNimi"/ARKISTO/HISTORIAT/"$ValitunTeksti"  "$KansioJohonSiirretaan"/ARKISTO/HISTORIAT/"$ValitunTeksti"    
                           }
done
}


 
function koodaa { # f2
[[ -d $kanta/"$KansionNimi"/"$ValitunTeksti" ]] && echo kansiota ei voi koodata. Valinta siirtyy takaisin tiedoston kohdalle && read -p 'paina enter' && continue
[[ $(echo "$KansionNimi" | grep ARKISTO) ]] && apu=$arkistoonpoikettu/"${KansionNimi##*\/}" && gedit $kanta/"$KansionNimi"'/'"$ValitunTeksti" "$apu" && continue # toimia ARKISTOssa ei arkistoida, ainoastaan käydään hakemassa koodi 178 uusikoe
[[ ! -f $kanta/"$KansionNimi"/'ARKISTO/SKRIPTIT/'"$ValitunTeksti"/1 ]] && cp $kanta/"$KansionNimi"/"$ValitunTeksti"  $kanta/"$KansionNimi"/'ARKISTO/SKRIPTIT'/"$ValitunTeksti"'/'1
Suurin_numero=$(ls $kanta/"$KansionNimi"/'ARKISTO/SKRIPTIT/'"$ValitunTeksti" | sort -g | tail -n 1)
apu=$kanta/\'"$KansionNimi"\'/\'"$ValitunTeksti"\'
for n in $(ls --hide=0 $kanta/"$KansionNimi"/'ARKISTO/SKRIPTIT/'"$ValitunTeksti" | sort -g | tail -n 6); do apu="$apu"' '$kanta/\'"$KansionNimi"\'/'ARKISTO/SKRIPTIT/'\'"$ValitunTeksti"\'/$n; done
## laheta kirjasto-funktion kopio arkistoon mikäli kirjastoa kutsutaan
funktiokirjasto=$(grep  FUNKTIOKIRJASTO $kanta/"$KansionNimi"'/'"$ValitunTeksti" | grep -v ARKISTO | awk {'print $2'}  | tr "\n" "  " );  
[[ "$KansionNimi" = OMATSKRIPTIT/FUNKTIOKIRJASTO ]] && funktiokirjasto='' # funktiokirjastossa ei liitetä toisia kirjastoja
[[ $funktiokirjasto ]] && {
apu="$apu"' '"$funktiokirjasto"; echo # lisää kirjastot editoitaviin
}
# apuu testaa onko kyseessä skripti
apuu=$(cat $kanta/"$KansionNimi"/"$ValitunTeksti" | awk '{print $1}'); [[ $(echo ${apuu:2:5}) = "/bin/" ]] && bash -n $kanta/"$KansionNimi"/"$ValitunTeksti" &>$kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
[[ -f $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe ]] && [[ $(cat -b $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe) < 1 ]] && rm $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
[[ -f $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe ]] && apu="$apu"" "$kanta/\'"$KansionNimi"\'/ARKISTO/SKRIPTIT/\'"$ValitunTeksti"\'/virhe
TiedostonAikaleimaAlussa=$(stat --printf %y $kanta/"$KansionNimi"/"$ValitunTeksti" | awk '{ print $2 }')
eval gedit "$apu"
while [ $TiedostonAikaleimaAlussa = $(stat --printf %y $kanta/"$KansionNimi"/"$ValitunTeksti" | awk '{ print $2 }' ) ]; do clear; read -t 1 -N 1 -p "paina näppäimistöstä jotain nappulaa" apu; [[ $apu ]] && TiedostonAikaleimaAlussa=1; done
# wait $! # $!=edellisen prosessin PID. Wait odottaa prosessin PID loppumista.
[[ -f $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe ]] && rm $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/virhe
DIFF=$(diff $kanta/"$KansionNimi"/"$ValitunTeksti"  $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"'/'$Suurin_numero )
[[ "$DIFF" != "" ]] && cp $kanta/"$KansionNimi"/"$ValitunTeksti"  $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"'/'$(($Suurin_numero+1))
echo ""
}

function dokumentoi { # f4
[[ $(echo "$KansionNimi" | grep ARKISTO) ]] && gedit $kanta/"$KansionNimi"'/'"$ValitunTeksti" $kanta/"$KansionNimi"'/'"${KansionNimi##*\/DOKUMENTIT\/}_dokumentti" && continue # ehdon tarkoitus:toimia ARKISTOssa ei arkistoida
[[ -d "$KansionNimi"/"$ValitunTeksti" ]] && echo 'kansion dokumentti' && sleep .1
[[ ! -d $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti" ]] && mkdir -p $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"
[[ ! -f $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/0 ]] && touch $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/0
Suurin_numero=$(ls --hide="$ValitunTeksti"'_dokumentti' $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti" | sort -g | tail -n 1)
apu=''
for n in $(ls --hide=*_dokumentti --hide=0 $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti" | sort -g | tail -n 6); do  apu="$apu"$kanta"/"\'"$KansionNimi"\'/ARKISTO/DOKUMENTIT/\'"$ValitunTeksti"\'/$n' '; done
TiedostonAikaleimaAlussa=$(stat --printf %y $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$ValitunTeksti"'_dokumentti' | awk '{ print $2 }' )
eval gedit $kanta/\'"$KansionNimi"\'/ARKISTO/DOKUMENTIT/\'"$ValitunTeksti"\'/\'"$ValitunTeksti"\'_dokumentti\  $apu
while [ $TiedostonAikaleimaAlussa = $(stat --printf %y $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$ValitunTeksti"'_dokumentti' | awk '{ print $2 }' ) ]; do clear; read -t 1 -N 1 -p "paina näppäimistöstä jotain nappulaa" apu; [[ $apu ]] && TiedostonAikaleimaAlussa=1; done
DIFF=$(diff $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$ValitunTeksti"_dokumentti  $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/$Suurin_numero )
[[ "$DIFF" != "" ]] && cp $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$ValitunTeksti"'_dokumentti'  $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/$(($Suurin_numero+1))
reset;  
}

function hexeditoida_osoitettua_skriptiä { bless $kanta/"$KansionNimi"/"$ValitunTekstiTalteen"; }
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 13.04.11 - klo:07.32
liitä koodi tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot2
Koodia: [Valitse]
#!/bin/bash  
# petteriIII 2.4.2013
echo -e "funktiot paikasta:"${0%/OMATSKRIPTIT*}"/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot2 liitetään koodiin"

function lue_näppäimistöltä () { # Vanhoja vastauksia voi selata ja editoida. Historiatiedosto on nimetty kysymyksen tekstin mukaan. Jokaisessa kansiossa on omat historiatiedostot.
# kutsu: lue_näppäimistöltä <kysyttävän muuttujan nimi> <kysymysteksti jonka merkkivalikoimaa ei ole rajoitettu> . Kysytyn muuttujan arvo tosiaan muuttuu.
historiatiedosto=$kanta/"$KansionNimi"/ARKISTO/HISTORIAT/"$2"
[[ ! -f "$historiatiedosto" ]] && echo 'historian alku' > "$historiatiedosto"   # kysymykselle luodaan kysymyksen tekstin mukainen historia-tiedosto # clear
apu=$(eval echo \$$1)
[[ "$apu" != $(tail -1  "$historiatiedosto") ]] &&  echo "$apu" >>  "$historiatiedosto" # kysytty arvo viedään heti historiaan josta sitä voi siis kutsua jo ensimmäisellä kerralla
echo -e "\nEdellisiä vastauksia voi selailla nuolinäppäimillä. Myös editointi toimii. Kirjoita vaikkei kysymysmerkkiä näykään"
echo -e "ctrl-r tuo esiin historian normaalin reverse-search:in. Jos annat pelkästään ¤ niin palataan Skriptiajuriin\n"$2
HISTFILE="$historiatiedosto"
set -o history
read -e $1 # $1 on muuttujan nimi
HISTFILE=~/.bash_history
set -o history
[[ $(eval echo \$$1) = ¤ ]] && $kanta/OMATSKRIPTIT/"Skriptiajuri, näppäinversio" # mahdollinen ongelma
eval echo \$$1 >>  "$historiatiedosto" # arvo menee sekä historistiedostoon että palautuu kysyttyyn muuttujaan $1
}
 
function täytä_valittavat () {
kansio=$@ # kun listattavaksi tulee kansio jonka nimessä on välilyöntejä siirtyy jokainen sana omassa parametrissaan ja ne täytyy liittää yhteen
find "$kansio" -size 0b -delete; find "$kansio" -type f -name ?*'\~' -delete; find "$kansio" -type f -name delme -delete
[[ $(echo "$kansio" | grep ARKISTO) ]] && eval Valittavat=(".edellinen_kansio." " "     $(ls "$kansio" -Qv --group-directories-first)) || eval Valittavat=(".edellinen_kansio." " "     $(ls "$kansio" -Q --group-directories-first))
}

function HaeSenRinvinNumeroJollaViimeksiTyöskenneltiinTässäKansiossa() {
ValitunNumero=1
[[ ! -d $kanta/"$KansionNimi"/ARKISTO ]] && mkdir $kanta/"$KansionNimi"/ARKISTO && echo 1 > $kanta/"$KansionNimi"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa
[[ -f $kanta/"$KansionNimi"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa ]] && ValitunNumero=$(cat $kanta/"$KansionNimi"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa)
}

function synkronoida_kovalevyn_ja_tikun_omatskriptit {
lue_näppäimistöltä kansio "mikä on kansion nimi tikulla (tyhjä nimi käy myös): "
rsync --existing -arcuv /media/tikku/$kansio/OMATSKRIPTIT ~
rsync --existing -arcuv ~/OMATSKRIPTIT /media/tikku/$kansio
read -p 'paina enter jatkaakseesi'
}

function LueParametrit () { lue_näppäimistöltä Parametrit "$ValitunTeksti"" saattaa vaatia parametreja. Annapa niitä jos asiallisena pidät:"; }

function VarmistaEttäArkistotOnTehty () {
[[ $(echo "$KansionNimi"/"$ValitunTeksti" | grep /ARKISTO) ]] && return # ARKISTOon ei tehdä arkistoa
[[ -d $kanta/"$KansionNimi"/"$ValitunTeksti" ]] && [[ ! -d $kanta/"$KansionNimi"/"$ValitunTeksti"/ARKISTO/POISTETUT ]] && mkdir -p $kanta/"$KansionNimi"/"$ValitunTeksti"/ARKISTO/POISTETUT && return
[[ ! -d $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti" ]] && ( mkdir -p $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"; touch $kanta/"$KansionNimi"/ARKISTO/SKRIPTIT/"$ValitunTeksti"/0 )
[[ ! -d $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti" ]] && ( mkdir -p $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"; touch $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/0; echo " " > $kanta/"$KansionNimi"/ARKISTO/DOKUMENTIT/"$ValitunTeksti"/"$ValitunTeksti"_dokumentti )
# tavitaanko enää? [[ ! -d $kanta/"$KansionNimi"/ARKISTO/HISTORIAT/"$ValitunTeksti" ]] && mkdir -p $kanta/"$KansionNimi"/ARKISTO/HISTORIAT/"$ValitunTeksti"
echo '' # funktiossa on ehdottomasti tehtävä jotakin  ja noista muista lauseista ei ehkä suoriteta yhtään, ehdollisia kun ovat
}

function TalletaSenRinvinNumeroJollaNytTyöskenneltiinTässäKansiossa() {
echo $ValitunNumero > $kanta/"$KansionNimi"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa #koe
}

function TalletaMistäKansiostaEnsikerrallaAloitetaan {
apu=${KansionNimi%%[[:alnum:]]*}; KansionNimi=${KansionNimi:${#apu}} # siistitään kansionnimi alkamaan aakkosnumerolla
apu=${KansionNimi%[[:alnum:]]*}; KansionNimi=${KansionNimi:0:$((${#apu}+1))} # siistitään kansionnimi päättymään aakkosnumeroon
echo "$KansionNimi">$kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/KansionNimiAloituksessa
}

function muuttaa_tämän_kansion_nimen_suurille_kirjaimille () {
SkriptinNimi="$ValitunTeksti"
SkriptinNimi=$(echo "$SkriptinNimi" | tr [:lower:] [:upper:])
mkdir $kanta/"$KansionNimi"/"$SkriptinNimi"
cp -rf $kanta/"$KansionNimi"/"$ValitunTeksti"/*  $kanta/"$KansionNimi"/"$SkriptinNimi"/; rm $kanta/"$KansionNimi"/"$ValitunTeksti"  # ARKISTOT seuraa mukana
muuta_uusi_nimi_valituksi
}

function muuta_uusi_nimi_valituksi {
täytä_valittavat $kanta/"$KansionNimi"
for (( n=1; n<=${#Valittavat[@]}; n++ )); do [[ $SkriptinNimi = "${Valittavat[n-1]}" ]] && break; done
echo $n > $kanta/"$KansionNimi"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa # kokeiltava toimiiko
}

function sovellusvalikko {
[[ -f $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku1 ]] && ValitunNumero=$(cat $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku1)
avaimet="end=palaa Skriptiajuriin   home=lopeta Skriptiajuri"
Valittavat=('tehdä uuden skriptin tähän kansioon' 'tehdä uuden kansion tähän kansioon' 'poistaa tämän valitun kohdan' 'siirtää osoitettavaan kansioon osoitettavat kansiot tai skriptit' 'muuttaa tämän kohdan nimeä' 'muuttaa tämän kansion nimen suurille kirjaimille' ' ' 'etsiä esimerkkirivejä kuinka jotakin käskyä käytetään' 'etsiä kysyttävää ilmaisua skriptien tekstistä' 'etsiä missä skripti on kun muistaa sen nimestä jotakin' 'synkronoida kovalevyn ja tikun omatskriptit' 'rajoittaa tämän skriptin arkistossa koodien lukua' 'hexeditoida osoitettua skriptiä' 'ajaa valitun skriptin' 'muuttaa sanan kaikkialla OMATSKRIPTIT kansiossa' 'hakea man sivun ss64 comista' 'etsiä millä man_sivuilla puhutaan siitä toiminnosta jota pitäisi käyttää' 'etsiä skriptistä kontrollimerkit' 'kuvata tiedosto graafisesti')
ValitunTekstiTalteen=$ValitunTeksti
ValitseValittavistaYksi "Minkä toiminnon haluat suorittaa tälle: ""$ValitunTeksti" "$avaimet"
[[ $Tapahtuma = end ]] && return
[[ $Tapahtuma = home ]] && exit
Toimi="$ValitunTeksti"
ValitunTeksti=$ValitunTekstiTalteen
echo $ValitunNumero > $kanta/OMATSKRIPTIT/ARKISTO/ASETUKSET/haku1
$(echo $Toimi  | tr ' ' _ ) # välilyönnit muutetaan alleviivauksiksi.  huomioi että tämä on funktiokutsu
}

function kuvata_tiedosto_graafisesti () {
  gnuplot <<_EOF_
    set term postscript enhanced color
    set output "$kanta/testResults.dat.eps"
    set title 'testResults'
    p "$kanta/testResults.dat" u 1:2 w l
_EOF_
evince $kanta/testResults.dat.eps
}

function etsiä_skriptistä_kontrollimerkit () {
echo "Kontrollimerkit ovat joskus tarpeellisia eivätkä tarpeettomatkaan aina aikaansaa vikoja, mutta joskus ne invalidisoivat ja lisäksi niin ettei se näy ja usein ei huomaa etsiä."
echo "Ensiksi etsitään kontrollimerkit tyyppiä \n, nämä ovat yleensä tarpeellisia:"
[[ -f $kanta/"$KansionNimi"/"$ValitunTeksti" ]] && cat $kanta/"$KansionNimi"/"$ValitunTeksti" | tr -dc '[:cntrl:]' | od -c && echo && echo
echo 'Ja sitten kontrollimerkit tyypiltään:  M- ja: C- (Nämä ovat yleensä merkki "kontrollimerkeistä" ja usein tarpeettomia. Huomioi että ääkköset on poistettu)'; echo
cp $kanta/"$KansionNimi"/"$ValitunTeksti" /tmp/delme1
cat /tmp/delme1 | tr -d äöÄÖ > /tmp/delme2
cat -v /tmp/delme2 | grep -e M- -e C-
#    M-
read -p 'paina enter selattuasi'
}


function etsiä_millä_man_sivuilla_puhutaan_siitä_toiminnosta_jota_pitäisi_käyttää () {
lue_näppäimistöltä kiinnostuksen_aihe "mistä man-sivuilla pitäisi puhua: "
apropos $kiinnostuksen_aihe
read -p 'paina return'
}

function muuttaa_sanan_kaikkialla_OMATSKRIPTIT_kansiossa () {
echo "tämä toiminta vaatii koodin puukottamista. Koodi on paikassa: ~/OMATKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot2. Suojele välilyönnit ja erikoismerkit kenolla. Toiminta kestää noin minuutin jona aikana tulostuu yksi"
read -p "tai useampi kysymysmerkki. Muutettuasi koodia sammuta Skriptiajuri ja aloita sitten uudestaan. Aloittaakseesi paina enter"
# muutoslausekkeen selvitys: $'g/mikä/s//miksi/g\nw\nq' . Vain mikä ja miksi muutetaan.
shopt -s globstar
for file in $kanta/OMATSKRIPTIT/**/*; do
    [[ -f $file ]] && ed -s "$file" <<< $'g/IDE\ BASH-skripteille/s//Skriptiajuri/g\nw\nq'
done
shopt -u globstar
}

function hakea_man_sivun_ss64_comista () {
Valittavat=($(cat /home/petteri/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/käskyluettelo))
ValitseValittavistaYksi "valitse mistä käskystä haluat man-sivun"
firefox  http://ss64.com/bash/$ValitunTeksti.html
}

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
echo 1 > ~/OMATSKRIPTIT/"KOE- JA ESIMERKKISKRIPTIT"/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa
echo 1 > ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa
echo 1 > ~/OMATSKRIPTIT/OHJEITA/ARKISTO/ViimeksiValittuSkriptiTässäKansiossa
echo " " > ~/OMATSKRIPTIT/ARKISTO/APUTIEDOSTOT/näyttö
}

function command_not_found_handle () {
# käyttöjärjestelmä kutsuu automaattisesti tämännimistä funktiota mikäli skriptissä viitataan käskyyn jollaista ei löydy.
komennon_nimi=$1
shift
echo "ohjelma:"${BASH_SOURCE}" Rivino:"${BASH_LINENO}
echo "seuraavaa käskyä ei löydy: \""$komennon_nimi\"""
echo "käskyn argumentit ovat: ""$@"
echo
kaskysta_on_puhuttu_paketeissa=$(apt-cache search $komennon_nimi)
[[ $(echo $kaskysta_on_puhuttu_paketeissa | grep ^$1) ]] && paketin_nimi=$(echo $kaskysta_on_puhuttu_paketeissa | grep ^$1) ||
paketin_nimi= $(echo $kaskysta_on_puhuttu_paketeissa | awk {'print $1'})
echo " paketin määrittelyä: "$paketin_nimi
sudo apt-get install ${komennon_nimi} || echo "siitä on puhuttu paketeissa: "$kaskysta_on_puhuttu_paketeissa
exit
}

 
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 04.05.11 - klo:06.06
Laita seuraava koodi paikkoihin: ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, näppäinversio/arkistonkäyttö   ja: ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, hiiriversio/arkistonkäyttö
Koodia: [Valitse]
Arkistoon talletetaan melkein kaikki tekemisesi ja siellä ne pysyvät kunnes erikseen poistetaan. Näin senvuoksi että usein skriptiä tehdessä täytyy kokeilla kuinka skriptiin saa halutun toiminnon ja kokeilujen seurauksethan ovat usein sellaiset että kaikki ehjäkin hajoaa ja jäljelle jää vain kaipaus siitä että saisi sen vanhan tilanteen takaisin.

Siinä lakanassa joka tulee esiin skriptiä editoitaessa on numeroituja sivuja. Nämä numerot ovat arkistointinumeroita ja se suurin numero on sama kuin se mitä parhaillaan käsittelet - kun poistut koodaamisesta niin mikäli skripti muuttui vähänkin niin editoidusta versiosta tulee seuraava numero. Kun siis menet ARKISTOon sillä kansiotasolla jolla skripi on ja valitset sieltä: skriptit niin esitetään mistä kaikista skripteistä sillä kansiotasolla on arkisto-kopioita. Valitse se skripti jota käsittelet jolloin esitetään sen skriptin arkistonumerot. Jos muistat mikä sen jotenkin toimivan arkisto-numero on niin kun valitset sen niin gedit:iin luetaan tämä arkistoitu skripti ja se pöhköksi editoitu versio - kopioi se, talleta ja peräydy ARKISTO:sta sille perustasolle ja jatka skriptintekoa - se on nyt se kauan sitten jotenkin toiminut versio.

Mutta joskus et muista sitä numeroa ihan tarkkaan: silloin voit koodata niitä arkistoituja kopioita - jos skripti ei näytä oikealta niin palaa tekemättä mitään ja koodaa jotain muuta numeroa - kyllä oikea lopulta löytyy - ja sitten vain kopiointi, talletus ja perääntyminen.

Mutta joskus ei oikeaa skriptiä löydä sittenkään - sitten vain ajamaan niitä arkistokopioita ja kun joku toimii samallatavoin nikotellen kuin aikoinaan niin siinä se on - ja sitten vain kopiointi, talletus ja perääntyminen.
 

- joskus taas alat kaivata sitä pöhköksi editoitua. Sekin löytyy arkistosta ja sen arkistointinumero niitä suurinpia.
- dokumenttien kanssa on samankaltainen järjestely, niiden ajaminen kyllä päätyy vain editointiin.
- toiminta on pakko tehdä näin, mitään automaatteja ei voi tehdä. Sillä vaikka ne toimisivatkin ensimmäisellä kerralla niin ne tekisivät sen että jotain katoaisi; yleensä merkityksetöntä mutta joskus merkityksellistä.
Laita seuraava koodi paikkoihin: ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, näppäinversio/geditin ja päätteen asetukset   ja: ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, hiiriversio/geditin ja päätteen asetukset
Koodia: [Valitse]
Teoriassa gedit lopetaan painamalla CTRL-q tai: tiedosto-quit , mutta käytännössä voit lopettaa geditin myös sulkemalla geditin ikkunan.

Tehtäessä skriptiajurilla geditin alaisuudessa runsaammin skriptejä voit editoidessasi skriptejä lisätä editointi-ikkunaan haluamasi tiedoston sisällön omalle sivulleen painamalla nappulaa f2 kun teet seuraavat asetukset: näpäytä geditissä: muokkaa - asetukset - liitännäiset - ruksi kohtaan "ulkoiset työkalut" - sulje - työkalut - Manage external tools - laajenna ikkuna ja siirrä keskipalkkkia jotta näet sanat kokonaan - näpäytä vasemmassa ikkunassa kohtaa "Suorita komento"-näpäytä hiiriosoitin kohtaan "lyhytvalinta näppäin" - paina esimerkiksi nappulaa f2-kirjoita skriptin teksti ikkunaan nimeltään Muokkaa ja lopuksi paina : Sulje
skriptin teksti voi olla esimerkiksi:
#!/bin/sh
gedit polku/tiedosto         (minulla se on tällähetkellä: gedit ~/OMATSKRIPTIT/OHJEITA/matriisi ~/OMATSKRIPTIT/OHJEITA/merkkijono

Samoin saattaa kannattaa määritellä gedit näyttämään rivinumerot: mene geditiin ja näpyttele: Muokkaa-Asetukset/laita ruksi neliöön kohdalla: Näytä rivinumerot-sulje
- nämä ovat samat rivinumerot joihin virhe-ilmoitukset viittaavat.
- tekstien rivit on numeroitu aina: gedit vain määrätään näyttämään ne.

geditiin kannattaa tehdä myös asetus: muokkaa-Asetukset/laita ruksi neliöön kohdalla: korosta vastaavat sulut

geditiin kannattaa tehdä myös asetus: muokkaa-asetuksetliitännäiset/laita ruksi neliöön kohdalla: pika-avaus

päätteessä kannattaa tehdä asetus: muokkaa-profiilit-editoi ja laita ruksi kohtaan: "Use custom terminal size" - 240 saraketta 80 riviä ja: Vieritys-rajoittamaton

- kun geditissä siirtää hiiriosoittimen osoittamaan jotain välilehteä tulee hiiriosoittimen tekstiin välilehdellä editoitavana olevan tiedoston täydellinen polku.
- geditillä on paljon muitakin ominaisuuksia, esimerkiksi tiedostoselain jonka navulla voi liittää halutun tekstin omalle sivulleen, äskenkäytettyjen lista ... ________________________________________________________________________________________________________________________________________________________________________________
gedit:illä on kaksi toimintamuotoa ja Skriptiajurissa käytetään seuraavaa: kun Skriptiajuri syöttää sivun Geditiin niin Gedit sallii Skriptiajurin jatkaa taustaajona ottaen näytön ja näppäimistön hallintaansa. Tällöin Skriptiajuri voi siellä taustalla toimiessaan syöttää Gedit:iin uusia sivuja. Mutta mikäli IDE:ssä siellä taustalla käytetään jotain geditiin syötettyä sivua niin käyttö koskeekin sitä editoimatonta versiota kunnes gedit lopettaa. Siis siinävaiheessa kun geditiin on syötetty kaikki sivut täytyykin IDE siellä taustalla seisauttaa esimerkiksi read-lauseeseen mikäli se käyttää jotain gedit:iin syötettyä sivua. Siellä taustalla IDE sitten jää odottamaan kunnes se saa näppäimistöltä jotakin jonka se voi saada vasta sitten kun gedit lopetetaan ja IDE palaa edusta-ajoksi ja saa näppäimet. IDE:n virtuaalinäytön teksti kopioidaan myös fyysiselle näytölle kun IDE palaa edusta-ajoksi.

Mikäli geditiin syötettyä tekstiä on muutettu niin IDE voi "painaa itse näppäintä" ja toiminta jatkuu automaattisesti. Vain jos tekstiä ei ole muutettu joutuu sitä näppäintä painamaan ihan fyysisesti.
Talleta seuraava teksti paikkaan : ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, näppäinversio/nappulatekniikkaa
Koodia: [Valitse]
Näppäinversion nappulatekniikka: kun IDE käynnistetään avautuu melko normaali tiedostopuu.
 ____________________________________________________________________________________________________________________________________
|  enter=suorita        f2=koodaa, f4=dokumentoi, end=erikoistoimet, home=näytä ohjeet             17.19.2012 13:27  koodeja: 6      |
|  ollaan kansiossa:omatskriptit                                                                                                     |
|                                                                                                                                    |
|  .edellinen_kansio. broken-link.sh     ex10.sh            ex45.sh            exercising-dd.sh   bashnumbers.sh     redir3.sh       |
|  ARKISTO            brownian.sh        ex11.sh            ex46.sh            factr.sh           online.sh          redir4a.sh      |  
|  HTML               bubble.sh          ex12.sh            ex47.sh            fc4upd.sh          opprec-table.sgml  redir4.sh       |
|  anon.sh            ex13.sh            ex48.sh            fetch_address-2.sh ip.sh              pad.sh             redir5.sh       |    
|  abs-book.sgml      cards.sh           ex14.sh            ex49.sh            fetch_address.sh   isalpha.sh         ref-params.sh   |      
|  add-drive.sh       case4.sh           ex15.sh            ex4.sh             fibo.sh            iscan.sh           remote.bash     |      
|  agram2.sh          case-cmd.sh        ex16.sh            ex50.sh            fifo.sh            is_spammer.bash    reply.sh        |        
|  agram.sh           cdll               ex17.sh            ex51.sh            fifteen.sh         is-spammer.sh      resistor        |        
|  alias.sh           Change.log         ex18.sh            ex52.sh            file-comparison.sh keypress.sh        restrict        |          
|  allprofs.sh        collatz.sh         ex19.sh            ex53.sh            file-info.sh       kill-byname.sh     return-t        |          
|  alt-bc.sh          colm.sh            ex1a.sh            ex54.sh            file-integrity.sh  kill-process.sh    revpospa        |            _____________________________________________________________________________________________________________________________________  

 
- tiedostopuussa liikutaan niinkuin normaalistikin kun liikutaan ilman hiirtä: nuolinäppäimillä ja enterillä. IDE:ssä vain toimii myös
 vasemmalle- ja oikealle nuolet.
                
- kaksi ylintä riviä on otsikkoja, loput sivusta on näkymää tiedostopuuhun.

- näytön ylimmällä rivillä oikealla lukee: <skriptin tekoaika>    koodeja: <luku> joka kertoo montako kertaa skriptiä on editoitu.
 Sillä tehdäänpä skriptiin kuinka pieni muutos tahansa niin skriptistä tehdään uusi versio eikä minkään tiedon anneta tuhoutua.
 Ei skriptit vie sittenkää kovalevytilaa juuri ollenkaan.

- valittavien joukossa  ensimmäinen valittava on .edellinen_kansio. . Jos se on valittuna kun painetaan enter niin siirrytään alemmalle kansiotasolle.

- seuraavina valittavina ovat kansiot ja ne on aina kirjoitettu suurilla kirjaimilla. Jos joku niistä on valittuna kun painetaan enter niin siirrytään sennimiseen kansioon.

- seuraavina valittavina ovat tiedostot ja niiden nimet ovat yleensä kirjoitettu pienillä kirjaimilla.jos niiden kohdalla painetaan enter niin ensin tarkistetaan onko niissä oleva teksti käännös-kelpoinen BASH-skripti ja jos on, niin se laitetaan suoritukseen, jos ei niin sen koodi viedään editoriin käännös-virheiden kanssa. Jos valittu ei ole käännöskelpoinen mutta se on skripti niin sen teksti viedään editoriin ilman listaa käännös-virheistä.

- ei kansioiden eikä nimien pituutta eikä merkkivalikoimaa ole rajoitettu. Silloin näytössä ei ole sarakkeita tai niitä on  ainakin vähemmän.

- editoriin päästään myös painamalla f2 ja tällöinkin mikäli kyse on skriptistä niin erilliselle lehdelle viedään ne virhevistit mitkä syntyisivät käännöksestä.

- editoriin päästään myös painamalla f4, mutta tällöin editoriin ei viedäkään tiedostoa vaan sen dokumentti.

- nappia end painamalla päästään erikois-toimintoihin.

- kun nappia home (=ohjeita) painetaan niin jokainen tiedosto joka on OHJEITA-kansiossa luetaan gedit:n omalle sivulle. Siten kaikkia ohjeita voi editoida (itseasiassa se on suositeltavaa), uusiin ongelmiin voi tehdä uusia sivuja tai poistaa vanhoja sivuja: uudet ohjesivut ilmestyvät geditiin omille lehdilleen automaattisesti ja poistuvat kun niiden sisällöksi kirjoitetaan tyhjää. Myös ohjeista löytyy arkistosta kaikki vanhat versiot. Uuden lehden saat kun talletat jonkun vanhan uudelle nimellä ja editoit sen uuden sivun - talletus ei muuten tuhoa vanhaa vaan siirtää sen vain arkistoon.



Editorin ikkunassa otsikkorivillä on ensimmäisenä tiedoston nimi - sillä sivulla on tiedoston teksti.

Sen perässä on numeroituja lehtiä - ne on noudettu arkistosta ja ne ovat tekstin tuoreimmat versiot ja mitä suurempi numero sitä tuoreempi. Suurin numero on sama kui teksti - siis tekstiä voi rauhassa editoida koska alkuperäinen versio löytyy vierestä.

Näiden lehtien perässä saattaa olla lehti nimeltä virhe  ja se ilmestyy vain kun teksti on skripti jossa tulkin kertomat käännösvirheet.

Näiden lehtien perään tulevat lehdet jotka noudetaan erikseen asimerkiksi Avaus-toiminteella - ne voivat esimerkTeoriassa gedit lopetaan painamalla CTRL-q tai: tiedosto-quit , mutta käytännössä voit lopettaa geditin myös sulkemalla geditin ikkunan.


geditiin kannattaa tehdä myös asetus: muokkaa-Asetukset/laita ruksi neliöön kohdalla: korosta vastaavat sulut

geditiin kannattaa tehdä myös asetus: muokkaa-asetuksetliitännäiset/laita ruksi neliöön kohdalla: pika-avaus

päätteessä kannattaa tehdä asetus: muokkaa-profiilit-editoi ja laita ruksi kohtaan: "Use custom terminal size" - 240 saraketta 80 riviä ja: Vieritys-rajoittamaton

- kun geditissä siirtää hiiriosoittimen osoittamaan jotain välilehteä tulee hiiriosoittimen tekstiin välilehdellä editoitavana olevan tiedoston täydellinen polku.
- geditillä on paljon muitakin ominaisuuksia, esimerkiksi tiedostoselain jonka navulla voi liittää halutun tekstin omalle sivulleen, äskenkäytettyjen lista ... ________________________________________________________________________________________________________________________________________________________________________________
gedit:illä on kaksi toimintamuotoa ja IDE:ssä käytetään seuraavaa: kun IDE syöttää sivun Geditiin niin Gedit sallii IDE:n jatkaa taustaajona ottaen näytön ja näppäimistön hallintaansa. Tällöin IDE voi siellä taustalla toimiessaan syöttää Gedit:iin uusia sivuja. Mutta mikäli IDE:ssä siellä taustalla käytetään jotain geditiin syötettyä sivua niin käyttö koskeekin sitä editoimatonta versiota kunnes gedit lopettaa. Siis siinävaiheessa kun geditiin on syötetty kaikki sivut täytyykin IDE siellä taustalla seisauttaa esimerkiksi read-lauseeseen mikäli se käyttää jotain gedit:iin syötettyä sivua. Siellä taustalla IDE sitten jää odottamaan kunnes se saa näppäimistöltä jotakin jonka se voi saada vasta sitten kun gedit lopetetaan ja IDE palaa edusta-ajoksi ja saa näppäimet. IDE:n virtuaalinäytön teksti kopioidaan myös fyysiselle näytölle kun IDE palaa edusta-ajoksi.

Mikäli geditiin syötettyä tekstiä on muutettu niin IDE voi "painaa itse näppäintä" ja toiminta jatkuu automaattisesti. Vain jos tekstiä ei ole muutettu joutuu sitä näppäintä painamaan ihan fyysisesti.

 
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 21.05.11 - klo:05.36
BASH on ohjelmoinnin kannalta inhottava koska kehittäjät ovat sen inhottavaan tilaan jättäneet - tosin BASH:ista ei saa yleiseen ohjelmointiin kepaavaa mitenkään mutta  prototyyppien tekemisessä se on verraton.
Jokainen tietokoneita käyttävä osaa BASH:ia luonnostaan. Tämä luo harhakuvan siitä että BASH olisi helppo ohjelmointikieli. Itseasiassa BASH on niin vaikea käyttää, että skriptaus perustuu täysin kopiointiin - muuten kirjastot ovat kopiointi-automaatteja joten kaikki ohjelmointikielet perustuvat kopiointiin. Sillä itse tekemäsi koodi on kääpiö kirjastojen rinnalla.

BASH:issa on ohjelmoinnin kannalta kaksi puutetta ja ne molemmat on osittain ratkaistu:
- kehitysympäristönä toimii tekstinkäsittelijä eikä sillä pysty tekemään kunnollista versionhallintaa tai kunnollisia hakutoimintoja jotka ymmärtävät BASH-koodia.
- kirjastot puuttuvat. BASH tuntee kyllä kirjastot, ja mikäli BASH:illa koodaa on niitä pakko tehdä itse sillä kirjastot ovat kaikkien ohjelmien perusta. Koetapas ohjelmoida C:llä käyttämättä kirjastoja.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 11.06.11 - klo:16.33
Laita seuraava koodi paikkoihin: ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, näppäinversio/uudet käskyt   ja: ~/OMATSKRIPTIT/OHJEITA/Skriptiajuri, hiiriversio/uudet käskyt
Koodia: [Valitse]
- Valinnasta on kaksi versiota: näppäinversio ja hiiriversio.
  1. näppäinversion valintafunktiot ovat paikassa: http://forum.ubuntu-fi.org/index.php?topic=44605.msg296419#msg296419
  2. hiiriversion valintafunktiot ovat paikassa: http://forum.ubuntu-fi.org/index.php?topic=44605.msg295198#msg295198
- lisää skriptiisi valintafunktiot joko kopioimalla ne skriptiisi tai kirjoittamalla skriptisi alkuun rivi:
  . sen_tiedoston_nimi_ johon_olet_valintafunktiot_laittanut  (ensimmäinen merkki on piste)

- lisää skriptiisi valittavat Valittavat-matriisiin esimerkiksi:
  Valittavat=(1 2 3 4 5 kukko kana piiroisen_pässi "mikäli valittavassa on välilyöntejä täytyy se laittaa heittomerkkien väliin")
  tai:  Valittavat=({mistäluvusta..mihinlukuun..askel_jos_tarvitaan})
  tai:  Valittavat=$(tiedostolistaus "$Kansio") # käyttäen valikkohiirelle ja valikkonäppäimille kirjastojen funktiota
  tai kurki tekotapa ohjeesta ohjeet/matriisi minkä ohje toimii kaikille käskyille.
- lisää skriptiisi Valittavien muodostamisen jälkeen kutsu: ValitseValittavistaYksi "ohjerivi jos haluat määritellä sellaisen" "avaimet
  jos haluat määritellä niitä"
  avaimet määritellään tyyliin: "f2=tee uutta, f3=hävitä vanhaa ..."  . Tunnetut avaimet: insert, delete, end, home, f1, f2, f3, tai f4
                                                                                                                                             
  Palautusarvot ja huomautukset:
- skripti palauttaa valitun rivin tekstin muuttujassa ValitunTeksti ja järjestysnumeron muuttujassa ValitunNumero.
- skripti palauttaa myös muuttujan Tapahtuma jolla on arvona sen avaimen nimi jota on painettu valinnan suorittamiseksi.
- skripti palauttaa myös kutsussa olleen ohjerivin CRC32:n muuttujassa crc. CRC on 32-numeroinen ja se yksilöi ohjerivin hyvin.
- noiden perustoimintojen lisäksi toimintaa voi säätää tilanteeseen sopivaksi:
- jos et halua määritellä otsikkoa niin jonkinlainen otsikko muodostetaan automaattisesti. Otsikkorivi on rivi 2.
- skriptissä voidaan kutsua valikkoa monta kertaa vaihtaen välillä Valittavat
                                                                                                                                     
- Välillä eteen tulee tehtäviä, joiden suorittajista jotkut ovat ammattilaisia ja jotkut ei-ammattilaisia. Esimerkiksi kun koneen paketti-
  varastot halutaan tyhjentää niin ammattilainen antaa käskyn: "sudo apt-get clean" koska sen kone ymmärtää, mutta ei-ammattilainen ei saa
  sitä pakettivarastoa tyhjennettyä koskei tuommoista käskyä tiedä olevankaan. Mutta kumpikin osaa käskeä: "tyhjennä pakettivarasto" ja
  sitten ohjelma suorittaa koodimuunnoksen muotoon: sudo apt-get clean. Tämä koodimuunnos tapahtuu valinnan yhteydessä: matriisissa
  Valittavat on selväkieliset käskyt ja matriisissa ValitunArvo on vastaavana jäsenenä se koodimuunnettu. Matriisin ValitunArvo voi jättää
  määrittelemättä jos ei siitä katso olevan mitään hyötyä tai määritellä se osittain tai paloittain, esimerkiksi: ValitunArvo=({1..20..2})

                                                                                                                                                 
Sitten valikko-ohjelman rajoituksista:
- valittavat esitetään aina yhdellä sivulla. Ohjelma käyttää koko näyttöä. Mikäli valittavia on useampia kuin näyttöriveille mahtuu aletaan
  valittavia jakaa sarakkeisiin; sarakkeenpituus määräytyy automaattisesti
- hyödyllinen rajoitus: samaa kohtaa ei voi valita useampaa kertaa peränjälkeen painamatta välillä jotain nuoli-näppäimistä
- yleensä päätteen ohjeen pika-valinta on f12. Joskus se kuitenkin on f1 jolloin se täytyy vaihtaa - helpointa on olla käyttämättä f1:tä
                           
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 14.06.11 - klo:18.30
Skriptinteossa debuggaaminen on työläämpää kuin skriptinteko. Voi syystä asettaa koko debuggaamisen mielekkyyden kyseenalaiseksi: tavallaan siinä huonompi yrittää korjata parempaansa.

Kun skripti tekee jotain muuta kuin ohjelmoija tarkoittaa on hyvä voida tarkistaa missä vaiheessa toiminta alkaa mennä metsään. Xref_funktiot antaakin mahdollisuuden tulostaa skriptin muuttujien nimet, arvot, osoitteet ja tyypit(=muuttuja, jonomuuttuja tai matriisi). Myös muuttujaa vastava declare-lause tulostetaan mikäli sellainen löytyy. Siitä selviää mahdolliset lisämääreet: 'r=vain luettavaksi', 'i=vain kokonaisluku-muuttujille', 'a=tavallinen matriisi', 'A=assosiatiivinen matriisi', 'f=funktion nimi', 'F=tulosta funktion nimi ja sisältö' ja 'x=valmistele muuttuja EXPORT:tia varten'. Mikäli skriptissä on funktioita tulostetaan myös niiden funktiomäärittelyt (=ensimmäinen rivi).

BASH:in matriisin osoitteiden ei tarvitse alkaa nollilta eikä matriisin osoitteiden täydy olla perättäisiä - ja assosiatiivisessa matriisissa 'osoite' voi olla tekstiäkin. Xref tulostaakin muuttujien arvojen lisäksi myös osoitteet mikäli osoitteita on.

Mikäli matriisissa on vain yksi jäsen ja sen osoite on nolla niin sitä ei aina erota tavallisesta muuttujasta. Tulostettaessa on ihan sama määrääkö: echo $Muuttuja   tai: echo ${Muuttuja[0]} . Käyttämisessä niillä on eroja.

Määrittelemätön matriisi ei eroa määrittelemättömästä muuttujasta muuten kuin ohjelmalistauksessa saattaa olla declare-lause.

Kirjoittamaton sääntö on, että käyttöjärjestelmän muuttujien nimissä kaikki aakkoset ovat suuria. Itse tehtyjen muuttujien nimet eivät koskaan saa olla kirjoitettu pelkästään suurilla kirjaimilla vaan niistä tulee löytyä ainakin yksi pieni kirjain jotta Xref löytäisi ne. Yksimerkkiset muuttujanimet kuitenkin hyväksytään vaikka ne olisikin kirjoitettu suurella ja perässäkin voi haluttaessa olla numerot 0-9. Mutta niiden tulostuksessa saattaa olla kummallisuuksia.

Matriisi ja merkkijono jossa on välilyöntejä voivat tulostua samallatavoin.

Mikäli muuttujan arvossa on yksikin välilyönti tulee muuttuja laittaa lainaus-merkkien väliin.
- välilyöntejä on muuten toisentyyppinenkin: alt-gr-<välilyönti>. Tulostettaessa se on kuin normaali välilyönti, mutta sitä käsitellään niinkuin normaalia kirjainta. Tällaista "non-breakable"-välilyöntiä ei tarvitse laittaa lainaus-merkkien väliin.

Assosiatiivisen matriisin osoitteet voivat olla tekstiäkin mutta jos osoitteen tekstin laittaa lainaus-merkkien väliin tulevat lainausmerkit osoitteen osaksi. Muuten assosiatiivisen matriisin järjestys saattaa muuttua tulostettaessa sikäli kuin järjestyksellä väliä onkaan.
 
Jottet halutessasi käyttää skripteissäsi komentoa:tulostamuuttujat joutuisi kirjoittamaan funktioita erikseen jokaiseen skriptiin, voit kirjoittaa funktiomäärittelyt kerran kirjastoon ja kutsua ne skripteissäsi käyttöön lisäämällä skriptiesi alkuun lauseen: . /home/$(whoami)/omatskriptit/FUNKTIOKIRJASTO/Xref_funktiot
- rivin tulee siis alkaa pisteellä.

Kopioi kansioon ~/omatskriptit/FUNKTIOKIRJASTO seuraavat määrittelyt tiedostoon nimeltään: Xref_funktiot :

Koodia: [Valitse]
#!/bin/bash  
# petteriIII 21.2.2013
# Xref-ohjelma tulostaa muuttujien arvot mikäli niiden nimessä on ainakin yksi pieni kirjain tai kun niiden nimi on alle kaksi merkkiä pitkä.

# muutujien määrittelyssä ei lueta ohjelmalistausta muissa tarkoituksissa kuin:
# - luetaan declare-lauseet ja tulostetaan ne sellaisinaan mutta vaikka ne olisivat ristiriitaisia tulostuksen kanssa niin niitä ei käytetä.
#   declare-lauseitahan ei tarvitse olla ja mikäli se on ristiriidassa tulosteen kanssa on se todennäköisemmin väärä.
# - luetaan ja tulostetaan funktiokutsut.

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

function TulostaTekstijono () {
[[ $(eval echo \$$1) ]] && echo -n $1' on jono-muuttuja arvoltaan: ' && eval echo \$$1 || echo $1" on määrittelemätön"
}

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

function TestaaMuuttuja () {
MUUTTUJAN_OSOITTEET=$(eval echo \${!$1[*]})
[[ $(echo $MUUTTUJAN_OSOITTEET | grep " ") ]] && TulostaMatriisi $1 || {
MUUTTUJAN_ARVOT=$(eval echo \$$1)
[[ $(echo $MUUTTUJAN_ARVOT | grep " ") ]] && TulostaTekstijono $1 || TulostaMuuttuja $1
}
# $BASH_SOURCE ->  ${0}  = skriptiä kutsuneen nimi      
cat "${0}" | grep "declare".*" $1$"
cat "${0}" | grep "declare".*" $1 ".*"#"
cat "${0}" | grep "declare".*" $1="
echo
}

# function Xref () {
echo -e "Xrefiä on kutsuttu skriptistä:"${0}".   Kutsu tehtiin riviltä:"${BASH_LINENO[0]}"\n\n"
declare > /tmp/delme
for RIVI_DECLARE_LISTASSA in $(cat /tmp/delme)  
do
  [[ $RIVI_DECLARE_LISTASSA = TestaaMuuttuja ]] && break              
  [[ ! $RIVI_DECLARE_LISTASSA = *[\=]* ]] && continue                     # jos rivillä ei ole yhtäkuinmerkkiä niin rivin voi ohittaa
  [[ ${RIVI_DECLARE_LISTASSA:0:1} = \$ ]] && continue                     # tavallisesti muuttuja ei voi alkaa merkillä $.
  MUUTTUJAN_NIMI=$(echo ${RIVI_DECLARE_LISTASSA%%=*})                     # muuttujan nimeksi tulee merkit ennen yhtäkuinmerkkiä
  [[ $MUUTTUJAN_NIMI = *[[:lower:]]* ]] && TestaaMuuttuja $MUUTTUJAN_NIMI # jos muuttujanimestä löytyy yksikin pieni aakkonen niin Xref hyväksyy sen
  [[ $MUUTTUJAN_NIMI = [A-Z] ]] && TestaaMuuttuja $MUUTTUJAN_NIMI         # isolla kirjoitetut yksimerkkiset muuttujanimet hyväksytään
  [[ $MUUTTUJAN_NIMI = [A-Z][0-9] ]] && TestaaMuuttuja $MUUTTUJAN_NIMI    # [0-9] toistetaan niin monta kertaa kuin sallitaan nimessä olevan numeroita
done
rm /tmp/delme

APU=$(cat "${0}" | grep function | grep -v Xref | grep -v TulostaTekstijono | grep -v TulostaMatriisi | grep -v TestaaMuuttuja | grep -v TulostaMuuttuja)
[[ $APU > 0 ]] && echo "listaus skriptin funktioista:" &&  echo -e ' '"${APU[@]/%/\n}"  
}  
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 28.07.11 - klo:12.37
BASH:in read-käskyyn saa kyllä mahdollisuuden editointiin jos vai muistaa ottaa sen käyttöön. Mutta historiaa se ei tunne. Lisäsin Valikko_funktioihin käskyn luenappis joka toimii kuten käsky read, mutta siinä on sekä editointi-mahdollisuus että historia. Esimerkki sen käytöstä:

Koodia: [Valitse]
#!/bin/bash

. /home/$(whoami)/omatskriptit/FUNKTIOKIRJASTO/Valikko_funktiot

# pääohjelma
luenappis luku 'Kirjoitapa luku:' # siis tuo luku on se jota luetaan. Viestiä ( 'Kirjoitapa luku:' ) ei tarvitse kirjoittaa.
echo 'tänne tuli luku: '$luku     # luku voi olla tekstiäkin tai merkkijono.
read -p 'paina enter jatkaakseesi'

- tosiaan; Valikko_funktioiden koodi on kohdassa: http://forum.ubuntu-fi.org/index.php?topic=303.msg288767#msg288767
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 03.09.11 - klo:05.47
Kaikki ihmisen tekemä on "valettu" jossakin muotissa. Linuxissa tämän muotin nimi on "regular expression" elikä regex. Esimerkiksi päivämäärät tehdään muotissa jonka regex on: [0123][0-9].[01][0-9].[20][0-9][0-9][0-9]  (siis: pp.kk.vvvv). Kun halutaan tulostaa pitkästä dokumentista siinä olevat päiväykset tulostetaan dokumentti läpi "päivämäärä muotista"  ja kaikki mikä sopii tuohon muottiin tulostetaan sillä ne ovat päivämääriä.

- tarkan muotin tekeminen on vaikeaa vähänkin monimutkaisissa tapauksissa ja se onkin kokeellista hommaa ja teoriat vain kertovat mitä kannattaa kokeilla ja minkä pitäisi toimia. Sitäpaitsi en ole vielä nähnyt ohjetta joka ei olisi täynnä kirjoitusvirheitä ja jopa loogisiavirheitä - niitä on ilmanmuuta tässäkin.
- edellinen haku awk:illa: awk 'BEGIN {muotti="[0123]?[0-9].[01]?[0-9].[20][0-9][0-9]" }; $0 ~ muotti { print }' ~/ohje
- vaikka muottia yleensä käytetään grep, awk ja sed ohjelmien välityksellä toimivat ne yleensä itse BASH:issakin:
  pvm="31.12.2014"; echo ${pvm//[0123][0-9].[01][0-9].[20][0-9][0-9][0-9]/tämä on suomalainen paivays}
- bashissa on operattori =~ joka toimii jotenkin regex:ienkin kanssa. Sen käyttö: [[ $tekstijono =~ regex ]] && toiminto
  käsky =~ asettaa muuttujia: BASH_REMATCH koko regexistä ja BASH_REMATCH[n] regex:in jokaisen sulun järjestysluvun mukaan.

Koodia: [Valitse]
*         muotti kuvaa mielivaltaista määrää sen edessä olevia merkkejä. Siis a* vastaa joukkoa a-merkkejä ja a.* mielivaltaista merkkijoukkoa jonka edessä on a
+         kuten *, mutta joukko ei voi olla tyhjä vaan ainakin yksi merkki.  esim | grep -P ab+c => muotti sopii kun sana alkaa a ja loppuu c ja välissä yksi tai monta b:tä
-         joukon muodostaja ellei se ole ensimmäinen tai viimeinen merkki; tai jos sitä ei edellä \ 
?         kuten *, mutta joukko on vain yksi tai nolla merkkiä. Esim. grep -P ab?c sopii ac tai abc
                                                                      sed -re 's/ab?c/d/g' muuttaa sanat ac tai abc sanaksi adc             
.         muotti kuvaa yhden mielivaltaisen merkin, mukaanlukien rivinsiirron
[...]     merkkiryhmän ympärille laitetaan hakasulut
\|        sanojen väliin laitetaan \| ja hakasulkuja ei saa olla  (=or-toiminto, sed:issä toimii sellaisenaan mutta grep vaatii kytkintä -E tai voi käyttää suoraan egrep:iä)

^         ankkuroi haun rivin alkuun; huomaa että välilyönti lasketaan mukaan. Merkin ^ tulee olla hakutermissä ensimmäisenä   
$         ankkuroi haun rivin loppuun. $ pitää olla hakutermissä viimeisenä
\b        ankkuroi muotin sananojen alkuun, loppuun tai rivin alkuun tai rivin loppuun.
\B        ankkuroi muotin sananojen alkuun tai loppuun -> siis sana ennen on välilyönti ja niin perässäkin
\w        etsii konaisia sanoja
\W        kokonaiset sanat ei kelpaa?
\s        muotti alkaa "whitespace":lla
- ankkurit sopii sed:iin sellaisenaaan mutta grep vaatii ympäröimään ne lainausmerkeillä

[abcd]               mikä hyvänsä merkki listassa
[^abcd]              mikä tahansa muu merkki kuin listassa oleva. Lista voidaan kasata joukkona, esim a-z
"\([a-z]\)\1"        muotti kuvaa kahteen peräkkäistä samaa pien-aakkosta. Näitä takaisinpäin viittauksia voi olla 9 - "takaisinpäinviitattava" alkaa aina \(
[muotti1\|muotti2]*  muotti kuvaa jokaiseen joka sopii muotti1:een tai muotti2:een.
muott1muotti2        muotti kuvaa jokaiseen joka sopii sekä muotti1:een että muotti2:een.; esim. [0-9][0-9] merkitsee: kaksi numeroa peräkkäin
- merkit $, *, ., [, and \ menettävät listassa erikoismerkityksensä. Kuitenkin
- ilmaisut muotoa [.ch.] ja [=a=] ovat erikseen. Myös merkinnät \n and \t tunnistetaan listoissa.
| grep -Po '(?<=edessä).*(?=perässä)'  # tulostaa tekstin joka on hakuavaimien välissä

| grep -Po 'tätä_haetaan(?=.*tämän_täytyy_olla_perässä_mutta_tätä_ei_valita)'  # välissä saa olla tekstiä; kirjoita sanojen paikalle ne jotka ovat käytössä
| grep -Po 'tätä_haetaan(?!tämä_ei_saa_olla_perässä)'                          # välissä ei saa olla tekstiä
| grep -Po '(?<=tämän_täytyy_olla_edessä_mutta_tätä_ei_valita)tätä_haetaan'    # välissä ei saa olla tekstiä
| grep -Po 'tätä_haetaan(?<!tämä_ei_saa_olla_edessä)'                          # välissä saa olla tekstiä

 
Merkkijoukot (merkkijoukkojen ympärille kirjoitetaaan yleensä toisetkin hakasulut, esim. [[:lower:]]. Jos tässä esimerkissä kyse olisikin merkkijoukosta
jossa ei saa olla yhtään pientä kirjainta merkitään se: [^[:lower:]]
[:alnum:] -> [A-Za-z0-9]
[:alpha:] -> [A-Za-z]
[:blank:] -> [ \t] välilyönti tai TAB
[:cntrl:] -> [\x00-\x1F\x7F] kontrollimerkit
[:digit:] -> [0-9] , [^0-9] -> kaikki muut kuin numerot
[:graph:] -> [\x21-\x7E] näkyvät merkit
[:lower:] -> [a-z] pienet kirjaimet
[:print:] -> [\x20-\x7E] näkyvät merkit ja välilyönti
[:punct:] -> [][!"#$%&'()*+,./:;<=>?@\^_`{|}~-]
[:space:] -> [ \t\r\n\v\f] Whitespace characters
[:upper:] -> [A-Z] suuret kirjaimet
[:xdigit:] -> [A-Fa-f0-9] hexadesimaalit
- merkkijoukot laitetaan yleensä kaksinkertaisiin sulkuihin, esim. echo a | grep [[:lower:]]


seuraavat kuuluvat "regularexpressionin" laajennoksiin; ne vaativat esimerkiksi egrep-ohjelmaa tai grep -E
{i\}      kuten *, mutta jokko on täsmälleem i-kappaletta
{i,j\}    kuten *, mutta lukumäärä on välillä i-j
{i,\}     kuten *, mutta jotakin yli i. siis esimerkiksi: egrep ^.\{15\}A etsii sanaa jonka alussa on 15 mielivaltaista merkkiä ja heti niiden perässä A
{,1\}     edellistä kohtaa on nolla tai yksi
a{2,\}?   jokainen a-ryhmä, jossa on vähintään 2 a:ta  (2:n paikalla voi olla mikähyvänsä luku joka toimii miniminä)
\(regexp\) esim. \(abc\)* korvaa nollaa tai suurempaa joukkoa jonka jokainen jäsen on abc, kuntaas abc* etsisi joukkoa jonka edessä on ab ja perässä on nolla tai useampi c

Siis toisin esitettynä:
a*b          # yksi tai useampi a ja perässä yksi b
a\?b         # joko b tai ab
a\+b\+       # rivi alkaa kahdellä tai useammalla a:lla ja perässä yksi tai useampi b.
.*           # rivillä voi olla mitätahansa     
^main.*(.*)  # rivi alkaa sanalla main ja rivillä on jossain merkit ()
^#           # rivi alkaa merkillä #
\\$          # rivi loppuu kenoon
\$           # rivi päättyy dollari-merkkiin
[a-zA-Z0-9]  # merkkijono jossa on pelkästään aakkosia ja numeroita
[^ tab]\+    # rivin alussa TAB ja sen perässä merkkijono
^\(.*\)\n\1$ # kaksi samanlaista tekstijonoa ja niiden välissä rivinvaihto
.\{9\}A$     # tekstijono jossa on yhdeksän merkkia ja sitten A rivin lopussa
^.\{15\}A    # tekstijono jonka alussa on 15 merkkiä ja sitten A

if [[ string =~ regex ]]; then tee_jotakin; fi
   
http://en.wikipedia.org/wiki/Regular_expression#Character_classes

seuraavat escape-koodatut tunnetaan:
\t tab
\n newline
\r return
\f form
\a alarm
\e escape
\033 octal
\x1B hex
\c[ control
\l lowercase
\u uppercase
\L lowercase
\U uppercase
\E end
\Q quote
\w Match a "word" character
\W Match a non-word character
\s Match a whitespace character
\S Match a non-whitespace character
\d Match a digit character
\D Match a non-digit character
\b word boundary
\B non-(word boundary)
\A beginning of string
\Z Match only at EOS, or before newline
\z Anchor Match only at end of string
\G Anchor Match only where previous m//g left off
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 15.02.12 - klo:13.30
Yhdessä suhteessa pätevä ison sovelluksen laadun tarkistus on jättää sovellus välillä täysin rauhaan ja tehdä jotakin ihan muuta. Sitten paljon myöhemmin tarkistetaan toimiiko sovellus enää moitteetta ja saako sovelluksen nopeasti hallintaan korjauksien tekemistä varten. Tämä testi on nyt tehty skriptiajurille ja se toimi moitteetta. Esimerkiksi 12.04 ja unity vaativat koodi-muutoksia ja bugejakin tuli korjattua.    


Yksi ominaisuus tuli lisättyä skriptiajuriin (ominaisuus ei toimi kovin iäkkäillä Ubuntuilla):
Kun ajetaan skriptiä joka käyttää sellaista käskyä jonka koodia ei ole ladattu juuri siihen koneeseen mutta jonka koodi löytyy repoista niin käskyn koodi ladataan.
- käskyt löytyvät yleensä aivan toisen-nimisestä paketista kuin mikä nimi käskyllä on.
- toiminta ei vaadi skriptiin muutoksia silloinkaan kun skripti on tehty kauan sitten.
- tehdyt muutokset vain poistivat muutamia varoituksia. Toimintaan ne eivät siis vaikuttaneet.


Seuraavasta ohjeesta saa periaatteen kuinka geditiin lisätään ulkoisia komentoja:
Tehtäessä skriptiajurilla geditin alaisuudessa runsaammin skriptejä voit editoidessasi skriptejä lisätä editointi-ikkunaan haluamasi tiedoston sisällön omalle sivulleen painamalla nappulaa f2 kun teet seuraavat asetukset: näpäytä geditissä:muokkaa-asetukset-liitännäiset-ruksi kohtaan "ulkoiset työkalut"-sulje-työkalut-Manage external tools-LAAJENNA IKKUNA JA SIIRRÄ KESKIPALKKIA JOTTA NÄET SANAT KOKONAAN-näpäytä vasemmassa ikkunassa kohtaa "Suorita komento"-näpäytä hiiriosoitin kohtaan "lyhytvalinta näppäin"-paina nappulaa f2-kirjoita skripti ikkunaan nimeltään Muokkaa ja lopuksi paina : Sulje
skriptin teksti voi olla esimerkiksi:
!/bin/bash
gedit polku/tiedosto         (minulla se on tällähetkellä: ~/omatskriptit/OHJEET/matriisi ~/omatskriptit/OHJEET/merkkijono ~/omatskriptit/OHJEET/matematiikka)


Samoin saattaa kannattaa määritellä gedit näyttämään rivinumerot mikäli koodaa paljon: mene geditiin ja näpyttele: Muokkaa-Asetukset/laita ruksi neliöön kohdalla: Näytä rivinumerot-sulje
- nämä ovat samat rivinumerot joihin virhe-ilmoitukset viittaavat.
- skriptien rivit on numeroitu aina: tämä on vain asetus siitä näytetäänkö ne.

Jos haluat aloittaa uuden ilmentymän skriptiajurista selataksesi toisella ohjeita ja samalla kun ensimmäisellä teet uutta skriptiä niin avaa ensimmäisen skriptiajurin ilmentymä normaalisti. Valitse sitten uusi työtila Dashboardin työtilan-vaihtimella ja paina uuden työtilan skriptiajuri-kuvaketta (jos painat Dashboard:n skriptiajurin kuvaketta palaataan ensin alkuperäiseen työtilaan).
- toiminta on tälläista vain 12.04:ssä. 11.10:ssä toimii hieman toisellatavalla ja ontuu sittenkin.
- samallatavoin voi avata vaikka kaksi aitoa firefoxia tai muita ohjelmia jotka eivät hyväksy toisiaan.
- siis myös työpöydälle pitää tehdä ohjelmalle kuvake.
-- koko asia esitettynä toisella tavalla: Dashboardin kuvake viittaa aina työtilaan 1, mutta kunkin työtilan oma kuvake viittaa omaan työtilaansa.

Olen jatkuvasti puhunut siitä että netin ohjeet ovat vanhentuneita. Niistä saa kammottavan ja *** tahallisesti !!!*** vääristellyn kuvan skriptauksesta. Esimerkiksi todellisuudessa BASH:in tekstin-käsittelyn pienet funktiot ovat poikkeuksellisen käteviä vaikka ohjeissa vakuutetaan niiden huonoutta.
Esimerkiksi tekstijonosta piti monimutkaisien valintojen perusteella ottaa palanen alusta, palanen keskeltä ja palanen lopusta. BASH-skriptinä helpohko yksinrivinen lause mutta muilla kielillä pitkä ja monia lauseita vaativa tehtävä. Koska olin uskonut virallisia vakuutteluja tein homman ensiksi todella vaikeasti, siihen kului karmeasti aikaa eikä se edes toiminut kunnolla.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 05.04.12 - klo:09.18
Komentorivin käytön yksi este on se, että komennot ovat pitkiä mikäli hyödyntää komento-kytkimiä, tiedostopuuta ja pitkiä nimiä. Ongelman ratkaisu on ennakoiva tekstinsyöttö.

Jokainen antamasi käsky viedään koti-kansion tiedostoon nimeltä .bash_history. Sitä voi selailla nuolinäppäimillä ja kun painaa esiintulleen kohdalla ENTER niin se suoritetaan. Mutta sitä voi käyttää paremminkin:
 
näppäile: !kap
- painettaessa ENTER suoritetaan ensimmäinen käsky historian lopusta alkuunpäin mennessä joka alkaa: kap

näppäile: !?näppi
- painettaessa ENTER suoritetaan ensimmäinen käsky historian lopusta alkuunpäin mennessä jossa jossain kohtaa on: näppi


- jos ominaisuuksia ei ole aikaisemmin käyttänyt niin ne ovat vähän arvaamattomia sillä ne toteutetaan välittömästi. Alkuunsa voi varmistua mihin ne viittaavat   painamalla ensin CTRL-r ja näppäilemällä sitten sen tekstin.
- hakusanassa voi olla kirjaimia vaikka kuinkamonta ja välilyöntejä voi olla vaikka kuinkamonta.
- historiasta tulee jatkuvasti käyttökelpoisempi mitä enemmän konetta käyttää. Tosin kannattaa tehdä muutos päätteen asetuksiin: avaa pääte - muokkaa - Profiilit - Muokkaa - Vieritys - ruksi laatikkoon: rajoittamaton. Tai kirjoita tiedostoon: ~/.bahrc rivi: unset HISTFILESIZE

- kun annat käskyjä niin historia-tiedostoon tulee aina uusi merkintä ja siis miljoonassa paikassa historiatiedostoasi on esimerkiksi käsky: sudo su
Tämänvuoksi historian selaamisesta tulee hidasta. Voitkin määrätä että jokakerran kun historiatietoihin lisätään käskyrivi niin ennen lisäämistä poistetaan edelliset täysin samanlaiset rivit antamalla käskyn: export HISTCONTROL=erasedups . Kun lisäät sen käskyksi tiedostoon ~/.bashrc niin se on päällä aina.

- voit editoida historiatiedostoa: gedit .bash_history

- joskus kirjoittaessasi pitkää käskyä tajuatkin että ensin täytyy antaa muita käskyjä. Kirjoita vaan käsky loppuun ja kirjoita käskyn ensimmäiseksi merkiksi # ja paina enter. Käsky menee historiaan kommenttina. Anna muut käskyt, hae historiasta tuo kommentoitu käsky ja poista sen alusta merkki # ja paina enter - nyt käsky tosiaan suoritetaan.

- kun olet aikaansaanut historiatiedoston jossa on kaikki mitä voit kaivata poista historiatiedoston kirjoitusoikeus käskyllä: CHMOD -x . ~/.bashrc ettei se sotkeennu.

- istunnon alkaessa tiedosto ~/.bash-history latautuu mistiin ja tätä muistissa olevaa käsitellään. Käskyllä: history -c nollautuu näytössä oleva historia, mutta levyyn se ei koske. Muistissa oleva historia kirjoitetaan levylle vasta kun  istunto loppuu.

- Kun Linuxin on tehty niin tarkoituksena on ollut että ***suuressa*** käyttäjä-joukossa kaikki saavat tukea toisilta - myös hyper-virtuoosit tarvitsevat apua ja ilman toisia kukaan ei ole mitään. Näin myös historian kanssa. Historiatietoihin voi käskyllä:   
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 19.04.12 - klo:12.03
Muutinpa skripti-ajurin tulostamaan virheensä tiedostoon. Kaikkiallahan kaiutetaan kuinka helppoa se periaatteessa on: käsky 2> tiedosto. Vaan ei toiminut skriptissä vaikka päätteessä toimikin. Luin miljoona verkkosivua löytääkseeni se maagisen ohjeen jolla uudelleenohjauksen saa toimimaan skriptissä. Lopulta törmäsin verkkosivulle jossa oli seuraavat tekstit, kylläkin ilman selityksiä:
program-name 2> error.log
command 2> error.log
- siis yksinkertaisesti: skriptille täytyy myös kertoa uudelleenohjauksesta.
- varmaankin homman löytää nyt monesta paikasta kun tietää täsmälleen mitä etsii. Sen käsittää ettei dokumentointia liiemmälti harrasteta, mutta olisi kiva jos oppaissa edes vihjattaisiin siitä aivan perusteiden yhteydessä.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: ajaaskel - 19.04.12 - klo:14.18
Kertoisitko jonkun esimerkin missä  2>virhe.txt ei toimi niin katsotaan ?   Kannattaa yleensä käyttää muotoa  2>>virhe.txt (eli kaksi väkästä= kirjoita olemassaolevan perään) jolloin toinen virhe ei ylikirjoita ensimmäistä vaan se virhe kirjoitetaan muiden tekstien perään siellä tiedostossa.  Jossain tilanteessa on kätevää ohjata merkityksettömät virheet yksinkertaisesti harakoille 2>/dev/null pois silmistä.   Jos tarvitset "sekä ykköseen että kakkoseen" menevät viestit tiedostoon niin
Koodia: [Valitse]
&>>kaikki.txt voisi olla sopiva.   Jos tarvitset sekä näytölle että tiedostoon niin "tee" komento on apulaisesi.

Edit:
Huomaa, että tuon kakkosen ja väkäsen välissä ei saa olla tyhjää, parempi kirjoittaa kokonaan yhteen kakkosesta eteenpäin.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 19.04.12 - klo:16.02
Lisäsin Skriptiajuriin funktion, joka muuttaa määrättävän sanan kaikissa Skriptiajurin tiedostoissa. Mutta nyt pähkäilen kannattaako sitä käyttää: kun muuttaa jonkun tärkeän sanan Skriptiajurissa ei ole minkäänlaisia mahdollisuuksia muuttaa sitä käsin kaikkialla, kyllä siihen tarvitaan ohjelmaa. Ongelma on se että muutoksia on niin monta, että jos aina kysyttäisiin:"saako tässä vaihtaa" niin joutuisi painelemaan enteriä viikon ajan, mutta jos ei kysytä niin tuleehan siinä pakostakin välillä harha-iskuja.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 04.05.12 - klo:20.34
Jo parivuotta olen käyttänyt kummallisia tiedostonimiä paljonkin eikä *mitään* vaikeuksia ole esiintynyt. Muutamassa erittäin haetussa erikois-tapauksessa toiminta on tosin puutteellista; esimerkiksi tiedoston nimeltää: * ollessa kansiossa nimeltää: *  .
- onkohan perää myöskään väitteissä että kummallisuuksia sisältävien skriptien toimiminen toisissa koneissa saattaa olla huono?  
- skriptiajuri ei välitä siitä, minkä kielisiä skriptejä sillä ajetaan. Ja sitä voi käyttää vaikka runoja tehtäessä.
- samoin funktiokutsuissa voi huoletta käyttää ääkkösiä. Välilyönnit täytyy kylläkin muuttaa alle-viivauksiksi. Skriptin listaus kylläkin muuttuu inhottavaksi vierailla kielillä.
___________________________________________________________________________________________

Hakutuloksiin ei pidä sotkea hakutuloksia ARKISTOista, sillä ARKISTOista-hakujen osumien määrä on todella suuri ja niissä on yleensä mahdottomasti toistoa. Mutta ARKISTOsta joutuu joskus etsimään kuten esimerkiksi:
Skripti voidaan tehdä lukemattomilla erilaisilla tavoilla. Eri toimintatapojen suorituskyvyt ja koot vaihtelevat "tuhatkertaisesti". Kun tekee skriptiä johonkin tehtävään kannattaakin kokeilla erilaisia toteutustapoja; ja periaate on että saman tehtävästä kaikki laitetaan samaan paikkaan eikä jokaisesta kokeilu-tavasta tehdä omaa projektiaan. Mutta kaikki kokeet sijoitetaan projektin omaan ARKISTOon. Kun myöhemmin huomaat että se aikaisempi tapa oli parempi saat haettua millainen se oli.  
Jos muistaa jotakin kyseiselle toteutustavalle ominaista antaa haku kyseisen projektin ARKISTOsta niiden arkistokappaleiden numerot joista kyseinen ilmaisu löytyy.
Arkistokappaleista voi lisäksi kokeilla kuinka ne toimivat ja editoriin saa kyseisen arkistokappaleen ja sen millaiseksi se on nyt editoitu. Joten kopiointi niiden välillä on helppoa.
__________________________________________________________________________________________

Tietokoneen vihulaisohjelmat muuttuvat jatkuvasti pahemmiksi eikä teoriassa mihinkään voi enää luottaa. Ei tilanne käytännössä ole vielä paha varsinkaan Linuxin suhteen, mutta pahempaa kohti mennään ja kun loppurysähdys tulee on se nopea ja paha.
Yhtä perustelua Linuxin turvallisuuden puolesta esitetään jatkuvasti: Linuxissa kaiken koodin saa tarkistettavakseen myös selväkielisenä tekstinä - käytännössä noista ajoista on jo kauan.
No, oletetaan että itse käyttöjärjestelmän koodi on puhdas. Entäpä ohjelmat ? Ne on käännetty eikä lähdekoodia saa.
Mutta skripteissähän on lähdekoodi ilmanmuuta mukana? Mutta useimmat skriptit käyttävät käännettyjä ulkoisia paketteja jotka vielä usein ovat peräisin Reino Rehdin PPA:sta. Lopputulos on se että voit käyttää vain itsetekemiäsi skriptejä.

Mutta skriptinteko on niin hankalaa kun niiden tekemiseen ei ole kunnollista käyttöympäristöä (=IDE:ä)? Skriptiajuri on moitteeton IDE ja se käyttää vain niitä paketteja jotka kuuluvat Ubuntun perusasennukseen.
_______________________________________________________________________________________
Tässä aikoinaan puhuttiin paljon 'just in time'-kääntämisestä ja onhan siinä järkeäkin: mitä sitä hommia tehdä ennenkuin tuloksia tarvitaan. BASH toimii muuten juuri tuolla periaatteella: mikäli tekee hommat oikein se hidastelee siellä missä se ei tunnu. BASH on todellisten virtuoosien tekemä: olisikohan jotenkin mahdollista että se toimii hitaasti koska ihminen tarvitsee "hitautta"?
Silti skriptien hitaus joskus harmittaa. Mutta toisaalta se merkitsee vain, että skriptiä ei voi tehdä kuinkavaan ->  " Jokainen skripti voidaan toteuttaa tuhansilla tavoilla. Skriptien suoritusajat vaihtelevat tuhatkertaisesti. Olet pätevä skriptintekijä jos pääset lähellekään kärkijoukkoa. Mutta mikäli jatkuvasti löydät niitä parhaita ratkaisuja olisi aika muuttaa lääkitystäsi. "
__________________________________________________________________________________________
Minulle on aina ollut ihmetyksen aihe se minkätakia skriptit halutaan nimettäviksi siten, että niissä on peräliitteenä .sh (tai ...)
Olen skriptannut nyt pari vuotta ammattimaisesti, enkä ole nimennyt ensimmäistäkään skriptiäni peräliitteellä .sh
Yhden idioottimaisen syyn keksin: siten yritetään kertoa: "tämä on skripti"
______________________________________________________________________________________________
Alkoi selvitä, miksi BASH on huonossa hapessa: asia on ihan sama kuin se ettei Linux saa vallattua markkinoita Windowsilta: pahin este siinä on se että firmojen IT:t osaavat toimia Windowsin kanssa hyvin mutta Linuxin kanssa hyvin huonosti ja vastustavat muuttamista Linuxiin kirjaimellisesti "verisesti".

Mikä on BASH:in Windows? Se on Python; avainhenkilöt osaavat sitä ja heille paluu BASH:iin olisi liian noloa. Aikoinaan kun aloin toimia BASH:in kanssa olin itsekin siinä käsityksessä ettei BASH:ista ole Pythonin rinnalla mihinkään. Mutta eteen on tullut omituisia tilanteita.

Jos oppaita kirjoittava harrastaa skriptausta ollenkaan niin  sitten PYTHON:ia tai PERL:iä. Eihän hän "vihollisen" hyviä puolia opeta - sillä BASH taitaa hakata PYTHON:it jos tilaisuus annettaisiin; siis se BASH jonka olemassaoloakaan ei tunnusteta.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 01.01.13 - klo:15.43
BASH:illa voi paitsi toteuttaa mitähyvänsä myös toteuttaa se ziljoonalla tavalla. Esimerkki siitä kuinka päiväys voidaan näksytellä hiirellä:

Koodia: [Valitse]
#!/bin/bash
kanta=${0%/OMATSKRIPTIT*}; echo 'tätä skriptiä ajetaan paikasta: '$kanta  
. "$kanta"/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkohiirelle # Kirjastosta liitetään koodi tiedostosta Valikkonäppäimille tämän skriptin koodiin.

IFS=". " read -r viikonpaiva paiva kuukausi vuosi tunti minuutti sekunti alue <<< $(date); unset IFS

while true; do
  Kuukaudessa31paivaa='1||3||5||7|8||10||12'; IFS="|"; set -- $Kuukaudessa31paivaa; unset IFS; [[ $(eval echo \${$kuukausi}) ]] && Valittavat=("vaihda vuosi" "vaihda kuukausi" {1..31})  
  Kuukaudessa30paivaa='|||4||6|||9||11||'; IFS="|"; set -- $Kuukaudessa30paivaa; unset IFS; [[ $(eval echo \${$kuukausi}) ]] && Valittavat=("vaihda vuosi" "vaihda kuukausi" {1..30})  
  Kuukaudessa28paivaa='|2|||||||||||'; IFS="|"; set -- $Kuukaudessa28paivaa; unset IFS; [[ $(eval echo \${$kuukausi}) ]] && Valittavat=("vaihda vuosi" "vaihda kuukausi" {1..28})  
  ValitseValittavistaYksi "Tämänhetkinen päiväys: "$paiva" "$kuukausi" "$vuosi" valitse uusi päivä:" " " $(($paiva+2))  
  [[ $ValitunTeksti = "vaihda kuukausi" ]] && Valittavat=({1..12}) && ValitseValittavistaYksi " valitse kuukausi: " "" $kuukausi && kuukausi=$ValitunTeksti && continue
  [[ $ValitunTeksti = "vaihda vuosi" ]] && Valittavat=({1900..2050}) && ValitseValittavistaYksi " valitse vuosi: " "" $(($vuosi-1899)) && vuosi=$ValitunTeksti && continue
  reset; paiva=$ValitunTeksti; echo 'Valitsit päivän: '$paiva" "$kuukausi" "$vuosi && exit
done


koodi valikkonäppäimille löytyy sivulta: http://forum.ubuntu-fi.org/index.php?topic=303.msg296419#msg296419

Miksi tehdä tämmöistä kun käyttöjärjestelmän oma on parempi ? Ja jos koodata haluaa niin miksei keskittyisi käyttöjärjestelmän käskyyn : cal ?

Eiköhän sekin vielä selviä.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: petteriIII - 10.02.13 - klo:12.30
- saadaksesi Skriptiajurin toimimaan anna ensi käsky: mkdir -p ~/OMATSKRIPTIT/FUNKTIOKIRJASTO && mkdir -p ~/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, näppäinversio" && mkdir -p ~/OMATSKRIPTIT/OHJEITA/"Skriptiajuri, hiiriversio" && mkdir ~/OMATSKRIPTIT/"KOE- JA ESIMERKKISKRIPTIT" && touch ~/OMATSKRIPTIT/"Skriptiajuri, näppäinversio" ~/OMATSKRIPTIT/"Skriptiajuri, hiiriversio" ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot1 ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot2 ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkonäppäimille ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkohiirelle ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/Xref_funktiot ~/OMATSKRIPTIT/"KOE- JA ESIMERKKISKRIPTIT"/kertotaulu ~/OMATSKRIPTIT/OHJEITA/{"Skriptiajuri, näppäinversio","Skriptiajuri, hiiriversio"}/{arkistonkäyttö,"geditin ja päätteen asetukset",nappulatekniikkaa,"uudet käskyt"} 

hae kopiopöydälle koodit sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg293780#msg293780
ja liitä toinen tiedostoon: ~/OMATSKRIPTIT/Skriptiajuri, näppäinversio
ja liitä toinen tiedostoon: ~/OMATSKRIPTIT/Skriptiajuri, hiiriversio

hae kopiopöydälle koodi sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg300081#msg300081
ja liitä se tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot1

hae kopiopöydälle koodi sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg300185#msg300185
ja liitä se tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/IDEfunktiot2

hae kopiopöydälle koodi sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg296419#msg296419  
ja liitä se tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkonäppäimille

hae kopiopöydälle koodi sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg295198#msg295198
ja liitä se tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/valikkohiirelle

hae kopiopöydälle koodi sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg303513#msg303513
ja liitä se tiedostoon: ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/Xref_funktiot

Ja kannattaa hakea yksi esimerkkiskripti ja muutama ohje, esimerkiksi: http://forum.ubuntu-fi.org/index.php?topic=303.msg292029#msg292029
ja liitä se tiedostoon ~/OMATSKRIPTIT/KOE- JA ESIMERKKISKRIPTIT/kertotaulu

Mikäli haluat IDE:en käyttöohjeita niin hae koodit sivuilta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg302036#msg302036
ja liitä ne ehdotettuihin paikkoihin

Uusien käskyjen ohjeet löutyvät sivulta: http://forum.ubuntu-fi.org/index.php?topic=44605.msg305254#msg305254
liitä ne ehdotettuihin paikkoihin


- anna käsky: chmod +x ~/OMATSKRIPTIT/"Skriptiajuri, näppäinversio" && chmod +x ~/OMATSKRIPTIT/"Skriptiajuri, hiiriversio"
- jos unohdat antaa IDE:lle suoritusoikeuden, saat ajo-yrityksestä virheviestin: permission denied
- Millä Linuxilla näitä IDE:jä käytätkin niin  Linuxeihin täytyy ladata tekstinkäsittely-ohjelma gedit. Yleensä se käy käskyllä: sudo apt-get instal gedit .
- yleensä IDE:jä voi ajaa mýös laitteen tiedostoselaimella (nautilus, Dolphin, Pluma ... ).
- yleensä näiden skriptien ajamilla skripteillä ei täydy olla suoritusoikeutta, ei riviä #!/bin/bash, nimien pituus ja merkkivalikoima ovat rajoittamattomia, nimien peräliite .sh kannattaa jättää pois ...
- skriptejä voi ajaa tikultakin. Käyttöoikeudet, polut ja tiedostomuoto vain oikeiksi.
- ajettaessa ensimmäistä kertaa IDE:t alustavat nyt OMATSKRIPTIT-kansion, joten enää ei tarvita kikkailua. Kumpikin IDE toimii samassa ympäristössä ja toinen alustaa myös toisen; ja siirryttäessä IDE:stä toiseen toinen jatkaa siitä mihin toinen lopetti. Muuten IDE:llä voi ajaa myös toista IDE:ä.

- käskyllä ~/omatskriptit/"Skriptiajuri, hiiriversio" voi ajaa skriptiä: Skriptiajuri, hiiriversio
ja käskyllä ~/omatskriptit/"Skriptiajuri, näppäinversio" voi ajaa skriptiä: Skriptiajuri, näppäinversio
- Skriptiajurit:t muuttuvat nyt niin nopeasti että kestää jonkiaikaa tarkistaa onko foorumille kirjoitetusta kaikki toimivaa
                                                          -------
Nyt alkaa tulla pientä tarvetta skriptien debuggaamiseen. Debuggaamiseenkin on monta keinoa ja yksi niistä kevyimmistä keinoista on laittaa epäilyttävän koodin-pätkän eteen:
set -x; trap "echo hit return;read x" DEBUG           ja koodin-pätkän perään:
set +x; trap "" DEBUG


IDE:llä on nopeaa kokeilla mitä perää on uskomuksissa. Esimerkiksi matriisin passaaminen parametrina, ainakin minulle sen on kerrottu olevan mahdotonta:

Koodia: [Valitse]
#!/bin/bash
function Tulosta_matriisi () {
eval echo -e "' '\${$1[@]/%/\\\n}"  
}

matriisi[1]="Marilla oli karitsa"
matriisi[2]="sen villa lumivalkoinen"
matriisi[3]="minne Mari menikään"
matriisi[4]="karitsa meni perässään"
Tulosta_matriisi matriisi
 
for n in {22..32}; do y[$n]=$n; done
Tulosta_matriisi y

- ziljoona jäseninen matriisi tulostuu myös. Kaksi-dimensioisen matriisin tulostukseen joutuu koodia puukottamaan vähän:
Koodia: [Valitse]
#!/bin/bash
function Tulosta_matriisi_rivi () {
eval echo -e \${$1[@]}
}

function Tulosta_matriisi_kokonaan () {
Sarakeluku=$2
Rivi=0
while true; do
  for (( n=1; n<=Sarakeluku; n++ )); do  
    [[ ! $(eval echo -e \${$1[n+$Sarakeluku*Rivi]}) ]] && return
    xxxx=$xxxx" "$(eval echo -e \${$1[n+$Sarakeluku*Rivi]})
  done
  Tulosta_matriisi_rivi xxxx
   xxxx=''
  let Rivi++
done
}  


matriisi[1]="Marilla oli karitsa"
matriisi[2]="sen villa lumivalkoinen"
matriisi[3]="minne Mari menikään"
matriisi[4]="karitsa meni perässään"
Tulosta_matriisi_kokonaan matriisi 1 # koska BASH:issa ei ole kaksiulotteisia matriiseja niin tässä on  tehty samoin kuin normaalistikin: kaksiulotteinen kuvataan yksiulotteisessa
# taittaen se rivi kerrallaan. Kutsun kirjoitusasu on: Tulosta_matriisikokonaan <tulostettavan matriisin nimi> <sarakkeiden luku tulosteessa>
# samalla menetelmällä voi kuvata kolmi-dimensioisetkin
echo
 
for n in {100..243}; do mahtavamatriisi[$n-99]=$n; done
Tulosta_matriisi_kokonaan mahtavamatriisi 12
read -p 'jatkaakseesi paina enter'

- tämä on käsittääkseeni ratkaisu BASH:in pahimpaan pulmaan: luullaan että yleiskäyttöinen funktio on mahdottomuus. Parametrin palautusta ei hyödynnetä, mutta sekin on näissä ja paljon parempana kuin yleensä onkaan: parametreja ei täydy edes määritellä.
- siis sama funktio tulostaa olipa matriisin muoto mikähyvänsä yksi- tai kaksiulotteinen.
Otsikko: Vs: Ohjeita shell-skriptaukseen (bash)
Kirjoitti: Tomin - 22.02.13 - klo:23.29
Voisit varmaan hostata noita tiedostoja kätevämminkin jossain palvelussa kuten:
Github: https://github.com/
Gitorious: http://gitorious.org/
Bitbucket: https://bitbucket.org/
Launchpad: https://launchpad.net/
Google Code: http://code.google.com/intl/fi/
Sourceforge: http://sourceforge.net/
tai joku muu sellainen: http://en.wikipedia.org/wiki/Comparison_of_open_source_software_hosting_facilities
Listasin tuossa ne mitä tuli mieleen. Ainakin osa vaatii jonkin versionhallinnan käyttöä, mutta se ei välttämättä ole huono asia.

Toinen juttu, joka helpottaisi tiedostojen jakelua on tarrapallo (http://linux.fi/wiki/Tarball) eli ne voisi pakata yhteen tiedostoon.

Kolmantena taidan siirtää nämä skriptiajurijutut omaan säikeeseen, helpottaa sopivien viestien löytämistä. :)

Muokkaus: Jaoin kyllä, mutta paljon viestejä jäi alkuperäiseen aiheeseen, koska foorumisofta ei ole kovin fiksu. Pikamoderoinnilla noita naksuttelisi äkkiä, mutta tämä ei anna kuin poistaa sitä kautta. Siispä puuttuvia viestejä pitää etsiä tuolta: http://forum.ubuntu-fi.org/index.php?topic=303.0

Vaivoin siirtelin noita yksittäin. Toivottavasti mitään olennaista ei jäänyt väliin ja jos jäi, niin saa mainita. Nyt menen nukkumaan.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: Tomin - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
 
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.

Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: nm - 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
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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ä ?
Otsikko: Vs: Skriptiajuri
Kirjoitti: nm - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
 
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.


Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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ä.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.



Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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?
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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:

Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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ä.


Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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)
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 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.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 10.12.23 - klo:13.20
Yritän tässä määritellä niitä mitä olen kutsunut vanhoiksi käskyiksi sillä eiväthän ne kirjaimellisesti ottaen käskyjä ole vaan dataan lisättäviä ohjeita siitä kuinka data tulisi esittää. Nopeilla käskyillä ei muuten ole matematiikan kanssa mitään tekemistä - silkkaa tekstikäsittelyä ne ovat.

Niiden nopeus tulee siitä että niiden toteuttamiseen tarvitaan vain merkki = tai käsky echo tai jotain senkaltaista nopeaa. Jos pelkästään tuloksia takastellaan niin datan muokkaamiseksi samallatavoin käytetään ohjelmina yleensä sed:iä, pieneltä osin myös awk:ia ja aivan mittömältä osaltaan myös bc:tä - mutta niillä tuloksen saaminen kestää niin kauan ettei niitä käyttäen saisi skripteistä nopeita. Ihmettelin aikanaan kun eräs virtuoosi sanoi että nopeutta haluttaessa pitää unohtaa sed, awk ja bc - täytyy siis olla niin että nopeiden skriptien olemassaolo on tiedetty aina?

Mutta enää en ihmettele sillä nuo vanhat käskyt suorittavat samantapaisia tehtäviä - kylläkin rajoitetummin mutta myös paljon nopeammin. Mutta jokatapauksessa ainoastaan sed, awk ja bc mielletään käyttökelpoisiksi - mikä suureltaosin taitaa johtua siitä etteivät virtuoosit ole koskaan tehneet noista BASH:in nopeista käskyistä minkäänlaista yhteenvetoa - sillä nopeiden käskyjen hyödyllisyys tulee täysin esiin vasta kun melkein kaikki käskyt skriptissä ovat noita vanhoja - sillä tulkki tulkkaa kerralla niitä isonkin joukon eikä tulkkia siis tarvita vähänväliä - joten joskus ne ovatkin parhaita.

Nopeat käskyt ovat vähän niinkuin BASH:in assembleria. Ja vaikka ne ovatkin ylivertaisia suorituskyvyltään niin luultavasti ne on hylätty samasta syystä kuin varsinainen assemblerkin : ohjelman tekeminen ja ylläpito niitä käyttäen on ihan liian kallista - rahallisesti jos skriptin ostaa ja jos skriptin tekee niin selkänahka paukkuu kauan. Virtuooseilla on siis ollut syytäkin tekoseensa - heitä on vaan on niin sopivaa mollata sillä onhan heillä leveät hartiat.

Toki nopeat käskyt toimivat vain niin hyvin kuin moitteettomat käskyt toimivat silloin kolmekymmentä vuotta siten. Esimerkiksi kun etsittävän alku on teksissä eri rivillä kun loppu niin plörinäksi menee. Samoin kirjoitusvirheitä ei suvaita ollenkaan.

***

- lukuja, tekstijonoja, matriiseja tai matriisien yksittäisiä jäseniä voidaan käsitellä 'äärettömän' monin eritavoin - on tosiaan mahdotonta muistaa käsittely-säännöistä pientä osaakaan vaan tiedostoista ne on haettava - eikä missään ole minkäänlaista yhteenvetoa vaan itse se on tehtävä - ja koska yhteenvedon tekeminen on liian suuri työ niin tuloksena on hutilointia ja sotkua - sillä yhteenvedon tekeminen kun olisi isollekin joukolle vaativa tehtävä. Ja nyt yhteenvedon tekeminen on hieman liian myöhäistä sillä ne vanhat käskythän on osin jo unohdettu - joten virtuoosit yrittävät tuhota BASH:in ennenkuin kukaan huomaa?

- nopeat käskyt toimivat vain yhden sanan alueella - mutta lauseesta tulee tavallaan yksi sana kun sen laittaa heittomerkkien väliin - tai myös muuttujalla nimeltään IFS voidaan määrätä sananväliksi merkki jota ei ole käytetty misssään jolloin monirivinenkin teksti tai tiedosto on yksi sana. Jokatapauksessa vanhojen käskyjen käyttämiseen ei tarvita jotakin grep-käskyn kaltaista järkälettä - kuten regex:ät tarvitsevat - joten ne ovat satoja kertoja nopeampia yhden sanan kanssa - tosin ne ovat myös satoja kertoja tehottomampia monirivisten tekstien kanssa sillä IFS:n kanssa leikkiminen on yleensä liian vaarallista - mutta oikeassa paikassa käytettynä ainoastaan nopeus merkitsee.

- BASH:issa jokaista käskyä käsitellään kymmenellä tavalla ennenkuin se lähetetään tulkattavaksi ja päteehän se nopeisiinkin käskyihin. Käsittelyjen suoritusjärjestys on päätetty etukäteen joten kaikki tehdään 'ennen tai jälkeen' monen muun tehtävän joten monet määreet kuten esimerkiksi IFS (= se määrää mikä merkki jakaa sanoja) muuttavat myöhemmin tulevat käsitteyt joskus ihan nurinkurisiksi. Tämmöinen  liian suuri monipuolisuus on myös painolasti kielen käytölle - BASH onkin turhan monipuolinen varsinaiseen ohjelmointiin - prottotyyppien tekemiseen BASH on tosin ihan kiva - ja alzheimerin välttelyssä BASH on erinomainen.

- voi olla varma että tästä kuvauksesta on moni merkittävä ominaisuus jäänyt pois sillä BASH:in kirous on se että kaikesta löytyy loppumattomiin uusia ominaisuuksia joten esimerkiksi kaikki käsikirjat ovat kelvottoman isoja tiiliskiven kokoisia raamattuja - esimerkiksi pääte-ohjelman käsikirja vaatisi viikkojen opiskelun ennenkuin homma olisi hanskassa - ja silti useimmat meistä käytävät päätettä käsikirjaa lukematta ja hyvin se sujuu niinkin - toiminta on silloin tosin joskus hidasta ja ärsyttävää mutta kaikki toimii kyllä jotenkin.

Jospa joskus tajuaisin päivittää tätäkin kuvausta - tai sitten ei, jottei tästäkin tulisi tiiliskiveä - sillä tiiliskiveä ei lue kukaan.

BASH on ainakin mielenkiintoista moniulotteista shakkia eikä hölmöilystäkään tule paineita - sillä onhan BASH siinä itsekin ihan omaa luokkaansa. Mutta jos saisi kirjastojen käyttämisen palautettua niin kuka tietää mitä BASH:ista tulisi.

***

Usein isoilla ja hitailla skripteillä on nopeat korvaajat - muihin kieliin verrattuna BASH on tosin hidas sittenkin. Koska ne on aikaisemmin tunnettu niin miksi ne on hylätty? Sillä ne ovat nopeampia, lyhyempiä ja ainakin tuntuvat vakaammiltakin.

Ehkäpä paras keino kuvata noita nopeita käskyjä on muutama esimerkki toimivista ohje-tyypeistä. Kaikki toimivat niin monella eritavalla ettei esimerkkejä kaikista voi antaa:

- tehtävä1: jaa annettu sana jonkun merkin kohdalta ja esitä joko etu- tai jälkiosa. Jakopiste voi olla myös sana - siis myöhemmin tehty uusissa käskyisä oleva 'parempi' cut-käsky joka jakaa vain yksittäisen merkkin ollessa jakopisteenä on varsinainen möhläys. Jakava merkki voi olla sanassa ensimmäinen jakavan merkin kaltainen tai sitten viimeinen. Jakava merkki voidaan esittää myös merkkiluokan osana, esimerkiksi: [1-9] -> siis nollan kohdalla ei tehdä mitään.
Esimerkiksi: desimaaliosa=${luku##*.} . Tai voidaan kirjoittaa pisteen sijaan: [.,] jolloin desimaalipisteenä voi olla joko piste tai pilkku - nopeudessa tuommoiset pikkujutut eivät tunnu vaikka niitä olisi montakin.

- tehtävä2: tuhoa, muuta tai tulosta sanasta jotakin määriteltävien ominaisuuksien perusteella. Esimerkiksi kun tekstijonona esitetystä desimaailuvusta pitäisi tehdä 'silmälle miellyttävä': poista kokonaisosasta etunollat ja desimaaaliosasta takanollat ja desimaalipistekin jos se jää viimeiseksi - eikä muihin nolliin saa kajota:
Koodia: [Valitse]
luku=${luku##+(0)}; [[ ${luku//[^.]/} ]] && luku=${luku%%+(0)}; echo ${luku%.}
Tällainenkin toiminta voidaan toteuttaa merkkiluokkien avulla - merkkiluokka on esimerkiksi: [0-9] elikä numroiden luokka - tai onhan noita: [:alnum:], [:alpha:], [:blank:], [:cntrl:], [:digit:],  [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:] ja [:xdigit:] - tai jotain muuta hakasulkujen välissä olevaa määritystä - kaksois-sulkuja kulemma kannattaa käyttää.

- tehtävä3. muuta joku sana/sanaryhmä jossain tiedostossa. Muutettavien sanojen ei tarvitse olla yhtäpitkiä - voit siis vaikka tuhota määrättävän sanan koko tiedostossa. Muutettavassa sanassa saa olla välilyöntejäkin. Muutettavia saa olla montakin samalla rivillä.
Koodia: [Valitse]
mika=BEGIN; miksi=ALOITA; < /boot/grub/grub.cfg readarray doku; printf "%s" "${doku[@]//"$mika"/"$miksi"}" | tee ~/poista_luettuasi
tulos ilmestyy näytölle ja myös kotikansion tiedostoon: ~/poista_luettuasi. Mitään ei varsinaisesti editoida - vaaraton esimerkki tämä on.

- tehtävä4: määrittele missä kohtaa annettavassa pitkässä sanassa on jokin kirjain/kirjainryhmä (= pos-funktio). Sekä etsittävässä ettäetsijässä saa olla välilyöntejä. Esimerkki:
Koodia: [Valitse]
isosana="Pitkät on puut Pisan mäellä, hongat Hornankalliolla"; pikkusana="Pisan m"; [[ "$isosana" =~ "$pikkusana" ]] && { echo -n 'pikkusana alkaa kohdalla:'; apu=${isosana%%$pikkusana*}; echo $((${#apu}+1)) ;} || echo 'pikkusanaa ei löydy'
- tästä olisi helppoa tehdä versio joka ilmoittaa kaikki ne paikat joista etsittävä löytyy.
- onko ihme että BASH:ia väheksytään kun tämöisistä super-nopeista ja vakaista on siirrytty epävakaisiin aikasyöppöihin?

tehtävä5: yhdistä kaksi edellistä grep-käskyn kaltaiseksi - siis tarkoituksena on käydä nimettävä tiedosto läpi ja jokaiselta riviltä miltä esittävä löytyy tulostetaan rivinumero ja löytökohta:
Koodia: [Valitse]
function grep2 () { < $2 readarray doku; rivino=0; for n in "${doku[@]}"; do rivino=$(($rivino+1)); apu=${n%%$1*}; [[ "$n" =~ "$1" ]] && { echo -n 'haettava löytyi riviltä: '$rivino' paikalta:'$((${#apu}+1)); echo ;} ; done ;}; grep2 "feature is" /boot/grub/grub.cfg
- siis kutsu on kokonaisuudessaan: grep2 mikä_ilmaisu mistä_tiedostosta. Sanassa mikä_ilmaisu saa olla välilyöntejä mikäli se laitetaan heittomerkkien väliin. Alkuperäinen grep ei edes salli heittomerkkejä ja ilman niitä se toimii hitaasti ja väärin.
- tämä on kolme kertaa hitaampi kuin alkuperäinen grep - mutta paljon nopeampi kuin BASH-skripti tavanomaisilla uusilla käskyillä. Silloin aikoinaan tällaisilla olisi hyvin voinut kilpailla grep-käskyn kanssa. Lisäksi tämän saa muokattua aivan sellaiseksi kuin käyttäjä haluaa.
- näistä nopeista käskyistä muodostetut skriptit lisäksi senjälkeenkun sen toimivat osat on koottu joko  toimivat tai sitten ei - mutta sitä uusien käskyjen raivostuttavaa taipumusta ei ole että alkuunsa saa virheellisiä tuloksia kunnes korjattuaan skiptiä miljoona kertaa alkaa saada oikeita tuloksia yhä useammin. Ovatko uudet käskyt siis paitsi satoja kertoja hitaampia niin myös loogisia pommeja?
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 14.12.23 - klo:18.41
Awk, sed ja bc ovat olleet tähänasti täysin ehdottomia nopeus-kuninkaita. Nyt ne ovat tosiaan menettämässä asemaansa 'BASH:in nopeille käskyille' - näin alkuunsa vasta muutamassa pienessä tehtävässä. Mutta esimerkiksi awk häviää taiston pahimmillaan 'kymmenkertaisesti'. Eivät ne tosin saa tuommoisia rökäletappiota kuin pienissä asioissa ja todella suurissa ne ovat nopeampiakin - myöntääköhän Linux niille enemmän resursseja? Eikä tosiaan kaikkia ziljoonia awk- ja sed-skriptejä kerkiä edes ajatella korvaavansa - mutta BASH varmasti osaisi. Tarkempi kuvaus siiä kuinka asiat tehdään:

Awk:ia, sed:iä ja bc:tä käytetään BASH:issa putkittamalla tutkittava niihin. BASH käyttää putkitusta vain kutsuessaan toisia skriptikieliä mutta kutsuessaan toisia BASH-skriptejä se käyttää mieluummin funktioita. Koska heti BASH-opetuksen alussa opetetaan käyttämään putkitusta mutta funktioista ei puhuta juuri sen enempää kuin että väitetään ettei BASH osaa funktioita kunnolla käyttää - joten eihän funktioiden käyttöäkään osata tekemisestä puhumattakaan. Esimerkki  awk:in käytetyimmästä toiminnosta:
Koodia: [Valitse]

# tämä on tosin ihan pieni mutta yleisin awk skripti:
echo  "10 20 30 40 50 60" | awk '{print $3}'

# näin se korvataan BASH:in 'nopealla käskyillä':
function awk2 () { echo ${@:$(($1+1)):1} ;}; awk2 3 10 20 30 40 50 60 

# tai jos heittomerkejä ehdottomasti haluaa käyttää: function awk2 () { apu=$1; set $2; echo ${@:$apu:1} ;}; awk2 3 "10 20 30 40 50 60"
# tai jos valittavissa on välilyöntejä niin: function awk2 () { echo ${@:$(($1+1)):1} ;}; awk2 3 'nyt saat kokea, koito' 'kokea kovaosainen' 'apen luista leukaluuta, anopin kivistä kieltä'
- BASH:in käyttämä tapa on tosin paljon hankalamman näköinen - mutta vain koska BASH:issa funktio-kirjastot on "kielletty" - muuten koko awk on sekin tavallaan kirjasto joten tilanne on epäreilu. Mutta jokatapauksessa BASH on kymmenkunta kertaa nopeampi - pärjääköhäm Pythonkaan taistossa hautaan jo saatetun BASH:in kanssa tässä pikkujutussa?
- awk on suurissa matemaattisissa toimissa paljon parempi kuin BASH. Eikä toistaiseksi voi edes aavistella kuinka noissa isoissa matemaattisissa laskuissa käy - ja onnistuvatko ne edes.
- awk:ssa on myös sadoittain pieniä muutaman merkin käskyjä jotka suorittavat pieniä ihmeitä - mutta eihän niistäkään misään kunnon yhteenvetoa ole.
- alkaa tuntua siltä että suhmurointia on liikaa ja käry on varmasti käynyt aikaisemminkin. Onko professorien valta niin ehdoton että asiat voidaan yksinkertaisesti vaieta kuoliaaksi?
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 15.12.23 - klo:15.45
Sed selviytyy paljon paremmin: muutettaessa tekstistä annettu sana kaikilla toiseksi kuluu  kymmenen kilosanan tiedoston käsittelyyn aikaa noin millisekunti niinkuin sed:illäkin. Pienemmillä tiedostoilla BASH on jopa 4*nopeampi ja isommilla jopa 4*hitaampi.
 
Koodia: [Valitse]
apu=$(cat /dev/urandom | base64 | head -c 10000); time printf "%s" ${apu[@]//a/alku}     # apu:sta muodostetaan ensin 10000 sanan tiedosto.  Tämä on pelkkää BASH:ia
apu=$(cat /dev/urandom | base64 | head -c 10000); time echo ${apu[@]} | sed 's/a/alku/g' # tämä taas käyttää apunaan sed:iä

# toteutustapoja on muitakin, esimerkiksi:
< /boot/grub/grub.cfg readarray doku; time { echo "${doku[@]}" | sed 's/a/alku/g' ;}

- myös sed on niin suuri ettei sen toimintojen merkittävää osaakaan saa tutkittua ihmisiässä.
- myös pieniä sed-skripteja on tolkuton määrä - ja myös ne tekevät pieniä ihmeitä. 
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 16.12.23 - klo:17.52
 
Käsitelläänpä sitten bc:

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

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

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

time pyöristä 1.22634 2          # tämä 'nopeilla käskyillä' toteutettu BASH-skripti kestää 0ms   
time bc<<<"scale=2; 1.22634/1"   # tämä bc:n lasku kestää 4ms - ja tulos on hieman virheelinen.
 
- tarkistelepa lausetta: $(($apu$merkki(( ${desimaaliosa:$2:1} >= 5 )) ))  -> BASH kokoaa ensin sellaisen tekstijonon kuin käsky määrää. Lähetettäessä tekstijono matematiikka-moottoriin sen osista jokainen määritellään sentyppisesti kuin hyvä tulee: siis jokainen osa voi olla tarpeen mukaan joko: tekstijono, numero, operaattori, laskutoimitus, funktiokutsu tai looginen arvo 0 tai 1 -> kaikki mitä sinne matematikka-moottoriin lähetetäänkin tuntuu toimivan.
- skandit funktion nimessä toimivat hyvin. Ei kyllä taida olla järkevää käyttää nimessä skandeja - mutta kokeillaan tämänkerran.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 19.12.23 - klo:10.40
Printf-käsky:llä on käynnissä ikuinen taistelu desimaalipisteen kanssa ja sillä lukujen koko rajoittuu 18 merkkiin. Kummankin puutteen voi poistaa 'nopeilla käskyillä' tehdyllä skrpteillä jotka osavat tulostaa  normaalissa esitysmuodossa annetun luvun tietellisessä esitysmuodossa tai päinvastoin - olipa luvuissa numeroita vaikka satoja - eikä desimaalipisteestä ole harmia:
Koodia: [Valitse]
function to_sci () { luku=$1
[[ ${luku:0:1} = - ]]  && { merkki=-; luku=${luku:1} ;} || { merkki=''; luku=${luku//+/} ;}
luku=${luku##+(0)}  # poistetaan etunollat - nimenomaan 0.xyx -> .xyz
apu=${luku%%.*}     # erotetaan kokonaiosa
exp=${#apu}         # lasketaan kokosasta positiivinen exponentti
[[ ${luku:0:1} = \[.,] ]] && { # katsotaan onko ensimmäin merkki desimaalipiste - silloin exponentti on negatiivinen
apu=${luku%%[1-9]*} # poistetaan kaikki siitälähtien kun ensimmäinen numero tulee desimaalipisteen jälkeisen nollasarjan perään. Siis tulos on desimaaipiste yksin jos nollia ei ole yhtään.
exp=$((1-${#apu}))  # lasketaan negatiivinen exponentti nollien lukumäärästä vähentäen yhden desimaalipisteestä
luku=${luku:1}      # palautetaan desimaaliosa jättäen desimaalipite pois
luku=${luku##+(0)}0 # poistetaa etunollat ja lisätään yksi peränolla
echo $merkki${luku:0:1}.${luku:1}e$(($exp-1)) # tulostetaan näin kun expnentti on negatiivinen - kokonaisosa on nyt ensimmäinen numero
} || { # halu dokumentoida aihuttaaa sen että ehtojen jälkeinen ryhmitys tulee rikkoa erotamalla nämä merkit tällätavoin
luku=${luku//[.,]/} # poistetaan desimaalipista sotkemasta
echo $merkki${luku:0:1}.${luku:1}0e$(($exp-1)) # tulostetaan näin kun exponentti on positiivinen - kokonaisosa on nyt ensimmäinen numero
} ;}

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


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

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

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

# testausta ja suoritusajan määritystä  - yksi muunnos kestää luokaa 0.25 ms
time for expo in {-55..55}; do from_sci 123456789012345678901234567890123456890.12345678901234567901234567890123456789e$expo; done
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 22.12.23 - klo:09.16
Kirjastojen puutteen takia BASH:issa on runsaasti seuraavankaltaista: haluttaessa erottaa tekstistä joku sana käytetään yleensä seuraavantyyppistä toimintaa :
Koodia: [Valitse]
echo $text |  awk '{ print $3 }'       # BASH:in vastaava toiminto on:
matriisi=($text); echo ${matriisi[2]}  # ja se toimii kymmenkunta kertaa nopeammin. Onhan koodi vähän pidempi eikä ihan yleisesti
                                       # tunnettukaan. Mutta silti ihmettelen miksei sitä käytetä sillä virtuoosien on pakko
                                       # tuntea tuommoiset. Halutaanko vähätellä BASH:ia vaiko edistää awk:ia?
                                       # Mutta entäpä jos BASH:issa olisikin kirjasto ja siellä funktio:
                                       # function write () { matriisi=($1); echo ${matriisi[$2]} ;}. Silloin käsky olisikin:
write "$text" 2                        # Ja toiminto olisi edelleen melkein yhtä nopeaa.

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

- kyse on ajoista 4ms ja 0.5ms. Mutta ajetaanpa toiminto kuinka monesti tahansa samassa skriptissä niin toiminta kestää jokakerran melkein yhtäkauan. Ja kun samanlaisia pikkujuttuja on paljon niin koko BASH alkaa tahmaamaan. 
- voi käskeä nyös: set yksi lensi yli käenpesän; echo $3    # se on lyhyt ja nopea - niinkuin BASH taitaa olla aina jos ei hölmöillä.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 23.12.23 - klo:15.35
'nopeat käskyt' ovat paitsi nopeita niin niillä myös helppo määritellä nopeita ja monipuolisia toimintoja sillä ne eivät ole loogisia pommeja niinkuin uudet käskyt helposti ovat. Tosin vanha käskyt ovat vaikeasti muistettavaa merkki-sotkua. Esimerkiksi kun pyydetään:

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

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


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

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

- monipuolisemmillakaan hauilla nopeus ei juurikaan muutu.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 25.12.23 - klo:11.19
Yritän jatkuvasti saada jotain järkeä siihen miksi virtuoosit ovat tehneet BASH:ista surkimuksen - selitän tätä siis itsellenikin: on pakko miettiä asiat paljon paremmin kun asiat kirjoittaa.

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

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

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

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

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

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

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

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

---

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

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

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

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

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

Ja tuloksena tästä 'kirjasto kiellosta' on että olemattoman pieniinkin ongelmiin tarkoitetut skriptit ovat tuhatrivisiä hirviöitä jonka lauseet koostuvat sanoista jotka ovat todella inhottavia kirjoitus-asultaan joten niitä ei edes muista vaan ne täytyy jokakerran hakea itsetehdyistä tiedostoista.
 
Omaan koneeseensa voi toki laittaa itsetehdyn kirjaston - minun koneessani iso kirjastoni on toiminut moitteettomasti jo yli kahdeksan vuotta - vaikka koneeni ovat vaihtuneet usein ja myös Ubuntun versiot vaihtunet parikertaa vuodessa.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 30.12.23 - klo:14.07
Ihan alkuunsa BASH:ia syytettiin eniten hitaudesta - ja hitaus olikin kiistatonta johtuen hitaista käskyistä - tulkattavasta käskystä tulee hidas jos siihen lisätään runsaasti ominaisuuksia jotka täytyy tulkata tarvitaan niitä tai ei - ja kussakin käytössä tarvitaan vain yhtä ominaisuutta ja muut ovat turhaa painolastia. Koska 'nopeat käskyt' osaavat tehdä vain yhtä asiaa ovat ne nopeita - ja näyttää yhä enemmän siltä että nopeus saattaakin usein olla paljon-paljon parempi kuin on luultu.

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

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

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

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

***

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

Toimintanopeuksia tosi-suurella tiedostolla:
Koodia: [Valitse]

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


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

***

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

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

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

Miten olisi:

Koodia: [Valitse]
tail -1 ~/temp
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 31.12.23 - klo:02.38
Oletpa oikeassa, sotkeuduin taas lahkeisiini. Taisi ylirasitus iskeä ja poistun lepäämään ainakin joksikin aikaa. Silti vielä: BASH:hissa on grep:in tai regex:in kaltaista nopeaa hakua, mutta kuitenkin ihan erilaista:
Koodia: [Valitse]

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

--- tai:
Koodia: [Valitse]

function takaosa () { apu="${1##*$2}"; echo ${apu%% *} ;}        # tulostaa ensimmäisen löydetyn perässäolevan
# tai: function takaosa () { apu="${1#*$2}"; echo ${apu%% *} ;}  # tulostaa viimeisen löydetyn perässäolevan
# tai: function takaosa () { apu="${1#*$2}"; echo ${apu% *} ;}   # tulostaa koko välin ensimmäisestä viimeiseen löydettyyn
                                                   
takaosa "kun mä kuolen sadetakkini sä saat
         sillä olen varma että
         pilv1enpääl ei sada vettä
         huh hah hei ja rommia pullo" "ma "
- tulostuu:että . Ja "a " tuostaa:pullo . Ja ma*sa tulostaa:da .  Ja: [0-9][iest] tulostaa:npääl. Kaikki niinkuin pitäisikin.
- huomioi että * ylittää sekä välilyönnit että rivinsiirrotkin.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 03.01.24 - klo:11.34
- tiedostosta lukeminen tapahtuu näin:
Koodia: [Valitse]
   takaosa "$( < /boot/grub/grub.cfg)" BE # tulostuu: GIN . Tai kun on syytä olettaa että etsittävä löytyy 100:lta ensimmäiseltä riviltä jättikokoista tiedostoa:
   takaosa "$( head -100 ~/tmp)" aa
- eivät nämä BASH-toteutukset vastaa nopeudeltaan läheskään sitä mihin esimerkiksi käsky:grep kykenee eikä näistä luultavasti nopeita saakaan. Eikä ilman kirjastoja näistä saa helppoja käyttääkään. Mutta jos kirjastoja käyttäisi niin grep jäisi monipuolisuudessa toiseksi sillä näistä voi räätälöidä hieman erilaisia versioita vaikka kuinkapaljon - aikaisemmin tuntemattomiinkin tarpeisiin. Tuntuu yhä enemmän siltä että virtuoosit ovat keksineet BASH:ille vaikeuksia ettei se kilpailisi sed:in, awk:in, grep:in ja muiden semmoisten kanssa.       

***

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


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

takaosa "ma1ma2makolme ma4 ma5
ma6

 ma7
ma8 ma9
ma10" ma

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

***

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

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


- etsintä siis huomioi kirjainkoon joten sillä siellä on keran Be
- koetapa:  takaosa "$( < /boot/grub/grub.cfg)" b
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 05.01.24 - klo:13.45
Tällä kertaa tarkoituksena on muuttaa edellä esitetty rekursiivinen versio tavalliseksi - siis tavallaan tehdä uudestaan - ja usein kun skriptn tekee täysin uudelleen niin se samalla yleensä yksinkertaistuu ja nopeutuu - ellei mähli:
Koodia: [Valitse]
function takaosa () { apu="$(echo ${1//\\n/ })"; while [[ "$apu" =~ $2 ]]; do apu="${apu#*$2}"; echo ${apu%% *}; done ;}
takaosa "$( cat /boot/grub/grub.cfg)" B
tulostuu:
EGIN
e
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN
EGIN

- löytyneistä ensimmäinen on tekstin alustapäin ja viimeinen lopustapäin.
- EGINIT tulevat sanoista BEGIN. Yksinäinen e tulee siitä että tiedotossa yksi lause alkaa: Be
- haku voidaan kirjoittaa myös: 
Koodia: [Valitse]
takaosa "$(readarray -t a < /boot/grub/grub.cfg; echo "${a[@]}")" B   
- hakuaika putoaa kolmasosaan kun hakutermiksi kirjoitetaan pieni b - vaikka löytöjä tulee neljäkertaa enemmän - olen äimänkäkenä siitä mikä tuommoisen voisi aiheuttaa. A/a on vähän toistapäin.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 06.01.24 - klo:19.39
Kun pakolliset rinkulat on nyt tehty niin pistetäänpä vauhtia masiinaan (siis toiminta oli: etsitään tekstistä jokainen haettava ja tulostetaan yksinomaan niiden sanojen loppu jossa haettava on
- siis tulostetaan välilyöntiin tai rivinloppun asti):
Koodia: [Valitse]
function takaosa () { for word in ${@:1}; do [[ "$word" =~ $1 ]] && echo ${word#*$1}; done ;}
# kutsut ovat kirjoitusasultaan: sana:takaosa haettava_teksti teksti_josta_haetaan
# -   rivinsiirrot sallitaan. Silloin teksti täytyy laittaa heittomerkkien väliin:
time takaosa ma "ma1 kkk kkkma2 ma3 ma4jjjjj gggggma5
ma6 ma7 hhhhma9ppppp ma10 xyz ma11 ggggma12"
- tai mikäli kyse on tiedostoon kijoitetusta tekstistä:
Koodia: [Valitse]
time takaosa B $( cat /boot/grub/grub.cfg)
- 'nopeisiin käskyihin' perustuvat skriptit ovat pienissä etsintätehtävissä nopeampia kuin sed-awk-grep-regex toteutukset  mutta mutta vähänkin isommissa etsintätehtävissä ne ovat hitaampia ja isoilla tiedostoilla jopa yli kymmenenkertaa hitaampia - mutta 'nopeista käskyistä' tehty skripti tarjoaa sellaista mikä muille olisi mahdotonta tai ainakin hyvin vaikeaa - ja 'nopeista käskyistä' tehtyä skriptiä voi tästäkin räätälöidä edelleen mihin tarkoitukseen tahansa. 

- myös grep+regex on varsin pätevä tallaisiin toimiin - mutta muistihirviö-skriptaajienkin täytyy opiskella sitä tosikauan ennkuin alkaa sujumaan. Eikä noiden muidenkaan skriptikielten soveltaminen yksinkertaista ole.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 09.01.24 - klo:12.39
Nyt alkoi selvitä miksi BASH on siinä tilassa kuin se on kun luin Ruotsin liikennekaoksesta, Norjan suojelupoliisin varoituksista jne jne. Asiat tiedostetaan ja konferensseja pidetään - mutta itse ei varmasti tehdä mitään eikä anneta toistenkaan auttaa vaan kielletään kaikkia tekemästä mitään sillä siitähän seuraisi että saattaisi joutua johtamaan koko hommaa joten viini, laulu ja naiset täytyisi unohtaa. Vastuuta pakoillaan vaikka ulkopuoliset selväsanaisesti sanovat että katastrofi on jo muodostunut.

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

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

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

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

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

onkoekasuurempi 12345679012345678.12345679012345678 12345679012345678.12345679012345678
onkoekasuurempi .1 0.1
onkoekasuurempi 1 .1
onkoekasuurempi 1 1
onkoekasuurempi +1 1
onkoekasuurempi -1 -1
onkoekasuurempi -1 1
onkoekasuurempi 1 -1
onkoekasuurempi 1.9 1.89
onkoekasuurempi 1.000000000000000001 1
onkoekasuurempi 2. 1.   # tai: onkoekasuurempi 2$ 1$ tai: onkoekasuurempi 2km/t 1km/t ...
- sekä desimaaliosat että kokonaisosa saavat olla 0 - 18 numeroisia, desimaalipilkku saa olla tai sitten ei ja verrattavat luvut voivat olla pelkkkiä numeroita tai niissä saa olla mukana mitähyvänsä lukuja tarkemmin määrittelevää tekstiä.
- tuleeko mieleen presedenssi kun antaa käskyn: luku=${luku//[^-.0-9]/} -> ei toimi jos kirjoittaa: luku=${luku//[^.-0-9]/}. Että yksinkertainen kieli?
- muuten esimerkiksi: onkoekasuurempi 6-2 4 -> 0 . Kokonaislukujen miinuslasku siis toimii mutta taitaa olla viisainta jättää muu matikka tässä yhteydessä pois.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 11.01.24 - klo:09.47
Funktion onkoekasuurempi lyhyempi versio osaa 'laskea' 32 numeron tarkkuudella 0.5 millisekunnissa. Silti lasku kuulunee skriptilajiin 'party trick' sillä eihän tämmöistä uskalla nykyään käyttää - mutta silloin kolmekymmentä vuotta sitten tämä olisi ollut kova juttu. Ja tiedähäntä mitä tästä saisi jalostettua - aikanaan se olisi kovastikin kannattanut mutta ei taida kannattaa enää tänäpäivänä. Tämä taas sarjassamme 'kummallisia sattumuksia'.
Koodia: [Valitse]
function onkoekasuurempi () { luku1=${1//[^-.0-9]/}; luku1=${luku1%.}; luku2=${2//[^-.0-9]/}; luku2=${luku2%.}; [[ ${luku1//[^-]/} ]] && m1=- || m1=''; [[ ${luku2//[^-]/} ]] && m2=- || m2=''; (( 10#0${luku1//.*/} == 10#0${luku2//.*/} )) && { desimaalit1=${luku1//*./}000000000000000000; desimaalit2=${luku2//*./}000000000000000000; (( $m1${desimaalit1:0:18} <= $m2${desimaalit2:0:18} )) && echo 0 || echo 1 ;} || { (( 10#0${luku1//.*/} <= 10#0${luku2//.*/} )) && echo 0 || echo 1 ;} ;} 
onkoekasuurempi 1234567890123456*1234567890123456 1524157875323881726870921383936 -> tulostaa 0 niinkuin pitäisikin
onkoekasuurempi 1234567890123456*1234567890123456 1524157875323881726870921383937 -> tulostaa 1 niinkuin pitäisikin

- 1234567890123456*1234567890123456 = 1524157875323881726870921383936
- ajatelkaa BASH:in monipuolisuutta - lukujen vertaamiseen tarkoitettu funktio on samalla myös osittain pätevä laskin - tekemättä kertakaikkiaan mitään.
- kyllä muutkin luvut toimivat samoin joten saisihan tästä tehtyä monenmoista.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 12.01.24 - klo:17.39
BASH oli kauan sitten kunkku - se jopa koettiin nopeaksi vaikka hidashan se on aina ollut eikä sen kykyjäkään ole koskaan paljoa hyödynnetty tietokoneen hoitamisen lisäksi - mutta eivät ne vaatimuksetkaan aikoinaan kovin kaksisia olleet. Mutta sitten virtuoosit siirsivät BASH:in satuun nimeltään: kuninkaalla ei ole vaatteita. Saman-nimisessä oikeassa sadussa tarvitaan pikkupoika sanomaan että alastihan kuningas on eikä komeasti vaatetettu niinkuin virtuoosit väittävät - ja senjälkeen kaikki muutkin uskalsivat myöntää etteivät he mitään vaatteita näe. Mutta BASH on päinvastainen tapaus: siinä virtuoosit väittävät ettei BASH:illa ole vaatteita. On melkein mahdotonta että tavis väittäisi vastaan ja sanoisi että BASH:in vaatteet ovat kyllä varsin resuiset mutta sittenkin vaatteita on - sillä häntä ei joko uskottaisi tai vaiettaisiin väitteet kuoliaaksi joten väittäjältä menisi maine - mutta minun maineeni meni jo kauan sitten joten voin väittää mitävaan.

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

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

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

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

Tuo parametri hommeli on muuten ovela juttu: luku on aina arvoparametri ja niin on tekstikin yleensä - mutta tekstijono tulkitaan nimiparametriksi mikäli saman-niminen muuttuja löytyy skriptistä jostain paikasta, vaikka myöhemminkin määriteltynä - suokaa anteeksi virtuoosit, eihän tämmöistä saisi kertoa - esimerkiksi tässätapauksessa muuttujasta jonka nimi on:numero puhutaan vasta funktiokutsun jälkeen joten tulkin täytyy sittenkin käydä skripti läpi ainakin kahdesti. Esimerkki:
Koodia: [Valitse]
function koe () { $1 numero; echo $numero ;}       # funktion nimeltä:koe parametri $1 on tekstijono:joo joka tulkitaan funktiokutsuksi ja muuttuja nimeltään numero sen nimi-parametriksi.
function joo () { readarray $1 < <(echo 12345) ;}  # tässä funktiossa $1 on nimiparametri nimeltään: numero - ja sille annetaan arvo 12345. Kun on palattu funktioon: koe ja jatketaan siinä
                                                   # olevan skriptin suoritusta välittömästi kutsu-paikan perästä ja tulostetaan muuttujan nimeltä:numero arvo käskyllä: echo $numero.
# annapa käsky:
koe joo 
# jolloin tulostuu: 12345
- siis vasta kääntäjä tekee päätöksen sitä minkä merkityksen se muuttujalle milloinkin antaa - tämä on siis aivan samanlainen tapaus kuin se jossa matematiikkamoottori tulkitsee sille annetun tekstin niinkuin hyväksi havaitsee.
- kun selittää kuinka joku menetelmä toimii kannattaa muuten selittää mahdollisimman paljon - silloin selittää myös itselleen joten tajuaa paremmin onko kaikki oikein. Ja vaikka selityksestä on useimmille lukijoilla pääosa itsestään selvää niin varmasti on joku sellainenkin lukija joka tarvitsee selitystä myös niissä itsestään selvissä kohdissa - ja sieltä pohjilta ne tulevat virtuoositkin kasvavat.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 15.01.24 - klo:18.36
 Olipa kerran suurvisiiri joka halusi kalifiksi kalifin paikalle - siis tässätapauksessa BASH:in paikalle. Mutta BASH oli aivan liian vahva jotta sitä olisi kannattanut haastaa. Siispä BASH:ia täytyi huonontaa paljon. Valhe on viisainta perustaa totuuteen joten kuka nämä tekikin puhui aina täysin totta mutta asetti sanansa niin taitavasti että käyttäjät älyttivät itsensä:
1. luulemaan etteivät esimerkiksi desimaalilaskut BASH:issa onnistu eivätkä siten edes yrittäneet tehdä niitä.
2. luulemaan että BASH kuuluu niihin mölleihin ohjelmiin joiden täytyy parametreja palauttaa - siis on ihan totta ettei BASH osaa parametreja palauttaa muttei palauttamisessa mieltä olekaaan.
3. hän myös häivytti desimaalilaskentaan pystyvät käskyt historian hämäriin uudella käskykannalla joka on desimaalilaskuissa tuhansia kertoja hitaampaa. Käytännössä tämä johtaisi siihen että vaatimatonkin desimaalilasku kestäisi uudella käskykannalla 10 minuuttia eikä kukaan viitsi niin kauaa yhtä pientä laskua tehdä.

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


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

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

HUOMAUTUS: ei ääretöntä lukualuetta ole nähtävästi mahdollista hoitaa moitteettomasti: esimerkiksi lasku luvuilla joissa eksponentti oli -8 tai -9 päätyivät virheeseen - sitä pienemmät ja suuremmat luvut toimvat. Siitä nämä 'nopeat käskyt' ovat mukavia että niitä saa tulla lisää monta ennenkuin se näkyy missään joten uusittu koodi on yhtä nopea kuin vanhakin.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 20.01.24 - klo:17.46
Edellisessä tehtävässä printf:n tehtävänä on muuntaa normaalilla tavalla esitetty luku tieteelliseen esitys muotoon: x.xxxxx e yy. 'Nopeilla käskyillä' tehtynä muunnos tapahtuu noin kuusikertaa nopeammin. Ei se koodin laadusta johdu vaan ohjelmien koosta: printf on 50K järkäle ja to_sci on vajaa kilo:
[
Koodia: [Valitse]
function to_sci () { apu=$1; [[ ${apu:0:1} = - ]]  && merkki=- || merkki=''; apu=${apu//[-+]/}; apu=${apu##+(0)}; kokonaisosa=${apu%%.*};[[ ${apu//[^.]/} ]] && desimaaliosa=${apu##*.} || desimaaliosa=0; [[ $kokonaisosa ]] && { expo=${#kokonaisosa}; echo $merkki${kokonaisosa:0:1}.${kokonaisosa:1}$desimaaliosa'e'$(($expo-1)) ;} || { apu=${desimaaliosa%%[1-9]*}; ekspo=$((${#apu}+1)); desimaaliosa=${desimaaliosa:$(($ekspo-1)):1}.${desimaaliosa:$(($ekspo))}; echo $merkki$desimaaliosa'0e'-$ekspo ;} ;}
# mutta ei ääretöntä kovin nopeasti saa testattua:tämä vaatii uskomattoman monia tarkituksia - tämä on vain alkua:
to_sci 1
to_sci 10
to_sci 010
to_sci 1000000
to_sci +1000000
to_sci -1000000
to_sci .1
to_sci .01
to_sci 0.01
to_sci -.01
to_sci +.01
to_sci -0.01
to_sci -0.01
to_sci 123456789012345678901234567890123456789012345678901234567890   # nimenomaan eksponentin tulee olla oikein
to_sci .00000000000000000000000000000000000000000000000001                      # nimenomaan eksponentin tulee olla oikein
to_sci .00000000000000000000000000000000000000000000000001234567890
to_sci -123.0124
to_sci -123.0000000000123

- näillä itsetehdyillä ohjelmilla on yksi voittamaton piirre valmisohjelmiin verrattuna: jos itsetehty toimii väärin niin sitten se korjataan. Mutta valmisohjelmalle et voi mitään.
- näillä itsetehdyillä on rajoitetussa määrin jopa toivottavaakin että joskus toimii väärin: tarkoituksenahan on aivojumppa. Ei merkitse kovin paljoa sekään että onnistuuko korjaamaan toiminnan oikeelliseksi - sekin riittää että yrittää.
- on inhottavaa ja pelottavaa tehdä uudentyyppisiä kokeita - sillä aivan varmaa on että jotakin on jäänyt huomaamatta ja varmasti joskus kompastuu - ja etukäteen ei voi tietää saako vikaa koskaan korjattua. Mutta todella tuntee elävänsä.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 22.01.24 - klo:21.48
Neliöjuuri kannattaa BASH:issa laskea luvun tieteelllisestä esitys-muodosta. Tieteelliseen esitysmuotoon ei kannata siirtyä käskyllä printf vaan tehdä funktio joka tekee saman muunnoksen täsmälleen samallatavoin ja toimii erittäin nopeasti - sillä myös käsky printf on suunniteltu hukkaamaan aikaa - printf on kyllä erittäin monipuolinen käsky sillä sitä voi käyttää myös säilyketölkkien avaamiseen.   
 
Koodia: [Valitse]

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

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

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

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

juurrettava=0000000000000;time sqrt $juurrettava


***

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

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

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

Myös BASH:in tarina on näemmä pelkkää historian kertausta - samoja tarinoita kerrotaan yhä uudelleen sillä uusia ei osata tehdä: tässäkin virtuoosit väittävät etteivät he ole tehneet mitään mutta kuitenkin pesevät kätensä kuin Pontius Pilatus.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 09.02.24 - klo:08.36
Tämä postaus meni uusiksi:

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

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

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

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

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

- mutta näitäkään toimintoja ei tiedetä hyödyntää sillä niistä ei opeteta missään. Epäoikeudenmukaisesti sanottuna: miksi opettaa kun on helpompaa sanoa ettei BASH osaa.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 20.02.24 - klo:23.37
BASH:in muisti on globaali - elikä jokainen muuttuja jonka arvoa muutetaan jossakin muuttuu kaikkialla muuallakin: mitä pääohjelmassa tehdään vaikuttaa kaikissa funktioissakin - ja mitä funktioissa tehdään näkyy pääohjelmassa ja toisissa funktioissakin - on kyllä parikin harvoin käytettyä tapaa eristää funktio - eli tehdä hiekkalaatikko, se on jo BASH:in idea tai vieläkin vanhempi - mutta niistä myöhemmin. 

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

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

- vaikka nimiparametrit voisikin palauttaa niin parametrien palauttaminen olisi BASH:issa silkkaa ajanhukkaa - ja siksi BASH ei parametrien palauttamista edes osaa. Tehty hommahan tämä  väärinkäsitys on joten virtuoosit ovat täysin varmasti sen aikoinaan tunteneet ja sitä käyttäneetkin.
 
- kun virtuoosit havaitsivat että:
Koodia: [Valitse]
eval \$$1
palauttaa myös viittaukset niin heille tuli kiire vakuuttaa että BASH:issa käsky eval on pahis eikä sitä saa käyttää. Eivät kai tienneet että onhan niitä muitakin samaan tehtävään kelpaavia käskyjä.
- esimerkiksi: BASH pitää kirjaa muuttujistaan ja antaa kirjanpitonsa käytettäväksi kaikkialla käskyllä: declare - se toimii myös funktioissa. Ja se on varmaankin jopa tehty siihen viittausten palauttamiseen - ja parametrien palauttamisen tarpeettomaksi tekemiseen.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 29.02.24 - klo:17.35
BASH:ista haluttiin päästä eroon jo ennenkuin Ubuntusta tuli ensimmäinen versio. Syy siihen oli sama kuin miksi huippu-kyvykäs assembler-kieli tapettiin aikoinaan: skriptit olivat sillä liian kalliita tehdä ja ylläpitää (se hinta maksettiin kylläkin yleensä vain koodaajan selkänahalla). Lisäksi koodarien uusi sukupolvi toi mukanaan uusia parempia kommervenkkejä hyläten kaiken vanhan. Muisa kielissä muutaman vuoden jälkeen alettiin hyväksyä jotakin siitä vanhastakin - mutta BASH:issa ei palattu osittainkaan vanhaan vaan jäätiin täysin siihen uuteen. Lisäksi silloin kauan sitten useimmat hoitivat tietokoneitaan itse ja ainoastaan siinä tehtävässä BASH on huippuhyvä. 

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

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

Yhteenvetoa BASH:in mustamaalaamisesta:

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

- tottakai kaikkeen on myös ihan kunnollisia syitä - esimerkiksi tietokonehan on aina turvallisuusriski ja vanhentuvat ohjelmat eritoten. Asioita tosin painotetetaan ihan ihmeellisesti.
- tarkoitus saattoi siis olla hyvä ja ettei vaan tajuttu mitä tuhottiin. Mutta eipä ollut ainoa kerta kun huonompi voittaa parempansa. Tällähetkellä BASH on kylläkin sotkettu niin syvälle suohon  ettei se varmankaan voi nousta sieltä koskaan.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 06.03.24 - klo:10.43
Mutta eipä BASH:ista ihan kohta taideta eroonkaan päästä päätellen siitä mitä vähäsen taas lueskelin - BASH:ista sinänsä vältetään puhumastakin mutta oletetaan sen kuitenkin toimivan sillä esimerkiksi tietokoneen ylläpito BASH:in avulla on helppoa kun voi ensin tutkia mikä tietokoneessa mahdollisesti on vialla ja perään asentaa tietokoneelle suojauksia - tosin vain harvat edelleen hoitavat konettaan itse. En tosiaan tiedä mutta aavistelen että pahikset kyllä hyödyntävät BASH:in osaamista mutta hyvikset eivät tajua että BASH on myös paras vastalääke.

Samoin pitää edelleenkin paikkansa että jos BASH:ia osaa on sillä nopea tehdä jollakin tavalla toimiva skripti kun haluaa selvittää kannattaako hommaan tehdä ohelma jollain nopealla kielellä.

Koko homma on tragikoominen, varsinkin jos alkaa levitä tieto siitä että kyllä BASH:kin osaa - ja jos muutamia temppuja on löytynyt jo niin pajonko niitä löytyy lisää? Esimerkiksi BASH:in käskyt osaavat paljon regex:istä - useat käskyt tottelevat niitä omalla tavallaan - olenkin viimepäivinä kokeillut niillä toimimista - en silti tiedä tuleeko niiden hyödyntämisestä mitään kunnolista. Kokeillut tosiaan sillä ei niistä ole hiiren hyppimääkään missään - lukuunottamatta vihjailuja sillä kaikki on tehty tarkkojen suunnitelmien mukaan mutta työt ovat jääneet dokumentoimatta - siis joku tietää.

BASH:ia alettiin tosiaan rapauttaa jo ennen kuin siihen oli saatu liitettyä kaikkia ehdottomasti tarpeellisia osia - tehtyjä ne jo tosin olivat mutta niiden liittäminen BASH:in koodiin olisi ollut melkoinen homma - ja ilmeisesti luultiin että eiköhän BASH kuole melko nopeasti ja työ olisi turhaa - ja tämä tuntui pahiten matematiikassa koska sille ei siihenaikaan BASH:issa juuri arvoa annettu - sillä desimaalien toimiminen on tosiaan välttämättömyys sille että matematiikasta voisi edes puhua. Eikä se oikein sytytä että aina täytyy käyttää ulkoisia matematiikkaohjelmia kun täytyy tehdä jotain matemaattista - vaikka ne ovatkin paljon parempia kuin BASH.

Esimerkiksi niin perustavanlaatuinen asia kuin maksimin/minimin määrääminen tekstijonosta tai matriisista: seuraava toteutus on se mitä tapaa opetetaan käyttämään - tosin tässä skripti on omituisen näköinen koska se on kirjoitettu funktiomuotoon:
Koodia: [Valitse]
function haemaksimi () { apu=$1; for (( x=1; x<=$#; x++ )); do  [[ $apu -gt $(eval echo \$$x) ]] && apu=$(eval echo \$$x); done; echo $apu ;}; unset apu; unset apu; for n in {1..9938}; do apu[$n]=$n; done; time haemaksimi "${apu[@]}"

- sen suoritus kestää noin 6 sekuntia - ja se toimii vain kokonaisluvuilla ja teksti sekoittaa sen kokonaan, myös desimaalipiste. Mutta maksimi/minimi löytyy melkein tuhatkertaa nopeammin sorttaamalla matriisi ensin nopealla C-kielisellä sorttaus-funktiolla joka toimii vaikka joukossa olisi desimaalilukuja tai tekstiäkin. Ja minimihän on senjälkeen matriisin ensimmäinen jäsen ja maksimi viimeinen - epämääräisyyksiä tulee paljon vähemmän kuin ennen ja niissäkin auttaa useimmiten kun säätelee sort-funktion kytkimiä - sillä jos sort käsketään sorttaamaan numeroarvon perusteella niin kyllä se sittenkin tekee parhaansa myös tekstin suhteen:
Otsikko: Vs: Skriptiajuri
Kirjoitti: nm - 06.03.24 - klo:13.44
Mutta eipä BASH:ista ihan kohta taideta eroonkaan päästä päätellen siitä mitä vähäsen taas lueskelin

Joo, Bash roikkuu vielä pitkään mukana Linux-jakeluissa. Applen macOS:ssä tosin vaihdettiin jo oletus-shelliksi Bashia edistyneempi ja monipuolisempi Zsh, joten se on käyttäjämäärältään ohittamassa Bashin. Ehkä osa Linux-jakeluista seuraa perässä tulevina vuosina. Zsh ei ole ihan nuori vaihtoehto sekään. Ensimmäinen versio on julkaistu vuonna 1990, eli vain vuosi Bashin ensimmäisen version jälkeen ja ennen Linuxin tuloa.

Esittely suomeksi: https://www.linux.fi/wiki/Zsh
Käyttöopas englanniksi: https://zsh.sourceforge.io/Guide/zshguide.html

Modernimpaa shell-ympäristöä kaipaavalle on vaihtoehtona myös mm. Nushell (https://www.nushell.sh/). Se poikkeaa eri tielle perinteisten Bourne-shellien polulta, mutta tarjoaa esimerkiksi sisäänrakennetun Sqlite-tietokannan (https://www.nushell.sh/commands/categories/database.html) sekä erittäin tehokkaita ominaisuuksia tyypitettyjen taulukoiden (https://www.nushell.sh/commands/categories/dataframe.html) käsittelyyn ja matematiikkaan (https://www.nushell.sh/commands/categories/math.html). Kehitteillä on myös laajempi standardikirjasto.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 08.03.24 - klo:17.20

Joo, Bash roikkuu vielä pitkään mukana Linux-jakeluissa. Applen macOS:ssä tosin vaihdettiin jo oletus-shelliksi Bashia edistyneempi ja monipuolisempi Zsh, joten se on käyttäjämäärältään ohittamassa Bashin. Ehkä osa Linux-jakeluista seuraa perässä tulevina vuosina. Zsh ei ole ihan nuori vaihtoehto sekään. Ensimmäinen versio on julkaistu vuonna 1990, eli vain vuosi Bashin ensimmäisen version jälkeen ja ennen Linuxin tuloa.


Kaikkea hyvää Zsh:lle sillä onhan BASH:issa paljon parannettavaa - mutta minä olen liian ryytynyt tapoihini siirtyäkseni Zsh:ta käyttämään.

Mutta hyppäsiköhän Apple sittenkin väärään junaan sillä kyse ei taida olla kielen kyvykkyydestä vaan sen käyttäjien asenteista - laulun sanoin: lökäpöksyni mun.

Enkä edes välitä siitä kuinka nopeasti skriptini toimivat huolimatta siitä että ajoitan ne aina - koska sehän taitaa kertoa mihin suuntaan kehitys on menossa - nopeampi ei oikeastaan ole parempi mutta hitaampi on varmasti huonompi. Mutta kyvykkyys sensijan kiinnostaa paljonkin. Ja päinvastoin kuin väitetään niin BASH:ilta tuntuu onnistuvan 'mikähyvänsä' - enkä tosiaan käsitä kuka sen kyvykkyyttä yrittää kätkeä. Tosin kaikki toimii hyvin hankalasti sillä eihän ongelmia kauan sitten ratkaistu ollenkaan samallatavoin kun nykyään - mutta paljolti samoja ne ongelmat olivat aikoinaan kuin nykyäänkin. Ja koodin pituushan ei kerro koodin nopeudesta paljoakaan vaan pidempi on useinkin nopeampi.

Mutta valitettavasti kaikki ponnistukseni menevät hukkaan sillä BASH:in kirjastojen toimimisen haittaaminen tuntuu olevan virtuooseille pyhä sota - ja kirjasto-kamaa kaikki edistyneempi on ja mikäli se ei kirjastoon päädy niin unohtuuhan se aikanaan.

***

Olen aina ihmetellyt niitä postauksia joita BASH skripteistä kirjoitetaan. Esimerkki on ulkomaisilta verkkosivuilta - sillä minä en maailmalle kirjoittele vaan poikkeuksetta ainoastaan luen. 

Käytännössä tapahtumat seuraavat toisiaan melkein aina seuraavalla tavalla: jollain ulkomaan verkkosivulla esitetään ongelma ja sille tulee esimerkiksi sata erilaista vastausta. Ensimmäiset vastaukset ovat tottakai vähän avuttomia mutta jo esimerkiksi kymmenes ratkaisee ongelman erittäin nopealla ja kaikissa tilanteissa toimivalla tavalla. Luulisi että vastukset loppuisivat siihen mutta niin ei koskaan käy vaan kelvottomien ratkaisujen tulva vain kiihtyy. Täytyy oppia etsimään se paras vastaus kaikista postauksista sillä se paras vastaus ei yleensä ole viimeisten joukossakaan. Olenkin alkanut epäillä että asioita sotketaan tahallisesti - tai sotkettiin silloin kauan sitten.

***

Seuraavista 'mahdottomista skripteistä' pikkuisen: nimi-parametrithan eivät kuulemma toimi BASH:issa? Tässä ne toimivat. Vertailun vuoksi esitän toiminnan käyttäen arvo-parametrejakin.

Tarkoituksena on tehdä skripti joka etsii maksimin/minimin silloinkin kun joukossa on desimaalilukuja. Aluksi täytyy kuitenkin kertoa kuinka desimaaalilukuja muodostetaan BASH:issa sillä kyllä BASH:in jotkut käskyt osaavat senkin ihan kikkailematta. Esimerkiksi anna käsky:
Koodia: [Valitse]
seq -s' ' 12600 -1.1234 1.1 | tr , . 
- seq noudattaa printf:n muoto-määräyksiä joten esimerkiksi seq laitaa tulostuksessaan Suomessa pilkun desimaalieroittimeksi. Jos se on alunperinkin piste niin tr on vain turha mutta virhe se ei silloinkaan ole.
- muuten seq toimii kaksimielisesti: se vaatii aina käskettäessä desimaalipistettä vaikka se antaisikin sen pilkkuna ulos.

Tämän avulla saa tehtyä sellaisen desimaaliluvuista muodostuneen matriisin jonka arvot ovat satunnaisessa järjestyksessä (ja jossa on jäseniä 11215 eli yhtämonta kuin edellisessä minimin määrittelyssä joka siis kesti 7 sekuntia):
Koodia: [Valitse]
sort -R <(seq -s' ' 12600 -1.1234 1.1 | tr ' ,' '\n.' )
seuraavaksi muodostetaan lauseen avulla matriisi ja etsitään siitä pienin arvo:
Koodia: [Valitse]

unset apu  # skriptin esimmäiseksi käskyksi täytyy kirjoittaa: unset apu. Sillä kun matriisi on määritelty jää se päätteen muistiin kunnes se tuhotaan käskyllä unset tai siirtytään toiseen päätteeseen - ja ellei unset:iä ole tulee sotkua kun määritelään apu uudelleen. Unset ei ole virhe vaikka matriisia ei vielä olisikaan.
apu=$(sort -R <(seq -s' ' 12600 -1.1234 1.1 | tr ' ,' '\n.' ))

# etsitään maksimi/minimi hakemalla matriisin arvot BASH:in kirjanpidosta nimi-parametrin avulla. Tämä on nopein menetelmä
function haeminimi () { sort -n <(declare -p $1) | tr -dc '\n'[.0-9] | head -2 | tail -1 ;}; time haeminimi apu     # selitys käskyille: | head -2 | tail -1 -> valitaan rivi 2
function haemaksimi () { sort -n <(declare -p $1) | tr -dc '\n'[.0-9] | tail -1 ;}; time haemaksimi apu

# tai etsitään maksimi/minimi ratkaisten matriisin arvot käyttäen käskyä: 'eval nimi-parametri' (mutta eval on jostain syystä virtuoosien kiroissa)
# apu on tässä esimerkissä nimi-parametri mutta siinähän voisi olla minkä matriisin nimi hyvänsä:
function haeminimi () { sort -n <(eval echo \${$1[@]} | tr ' ' '\n' ) | head -1 ;}; time haeminimi apu
function haemaksimi () { sort -n <(eval echo \${$1[@]} | tr ' ' '\n' ) | tail -1 ;}; time haemaksimi apu
 
# tai hetaan maksimi/minimi käyttäen arvo-parametreja:
function haeminimi () { sort -n <(echo "$*" | tr ' ' '\n') | head -1 ;}; time haeminimi "${apu[@]}"
function haemaksimi () { sort -n <(echo "$*" | tr ' ' '\n') | tail -1 ;}; time haemaksimi "${apu[@]}"

- näissa esimerkissä matriisin nimi on apu, mutta funktiot toimisivat samoin vaikka matriisin nimi olisi joku muukin
- ja nopeus on tosiaan kaiklla monisatakertainen siihen vertaavaan menetelmään verrattuna - ja toimitaan aina samalla tavalla riippumatta siitä millaista data on eikä milloin mitenkin niinkuin siinä hitammassa vertailussa joka tukehtuu jo desimaali-pisteeseenkin.
- muuten: BASH:issa ei kovin nopeasti pidä hyväksyä laskua oikeelliseksi vaikka se tuntuisikin toimivan. Samat testit tulee suorittaa eri päivinä kun kone on ollut välillä sammutettuna ja tehdä erilaisia testejä monta päivää - testejä samassa pääteistunnossa ja välillä vaihtaen pääteistuntoa, joskus tarkoin määritellyllä datalla ja joskus satunnaisella datalla, käännellen-väännellen ja välituloksia ottaen .... joten parin viikon kuluttua samasta aiheesta testin tekemisen ajatteleminenkin aiheuttaa paiseita ja on tehtävä välillä jotain muuta.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 12.03.24 - klo:08.46
BASH:in alkeita opetetaan monessa paikassa moitteettomasti - ja ainahan se on niin että kaikessa opetuksessa täytyy tyytyä vajaavaisiin opetuksiin, joitain asioita ei kannata kertoakaan, toisia painotetaan jotenkin ja vähänväliä tullee eteen sellaista jota ennen on sanotttu mahdottomaksi - mutta sen ratkaisu vain vaatii ihan uutta ajatustapaa - joka täytyy ensin opetella. Mutta BASH:in asiat alkoivat jo alkuunsa vinoutua: annettiin alkeisopintojen jälkeen ymmärtää että tässä tämä oli kirjoittamalla 'advanced guideja' joissa nimestään huolimatta ei ole mitään edistyksellistä - ihan kunnollisia opastuksia alkeisiin ne kyllä ovat - mutta niiden opetuksien jälkeenhän ne edistyneemmät menetelmät vasta alkavat. Ihan toinen asia on että kannattaako BASH:ia opiskella jos sitä kuolevaksi kieleksi luulee. Ja opetuksessa piisaa puutteita muutenkin:
- ei esitetä opetetun heikkouksia joten ollaan tyytyväisiä epämääräisesti toimiviin skripteihin ja todetaan vain että BASH on niin kelvoton ettei parempaa saa aikaiseksi.
- ei vihjatakaan kuinka pitäisi toimia. Kieltämättä edistyneemmät käskyt ja käskyryhmät ovat ulkonäöltään niin kummallisia ettei niitä kukaan halua käyttää tai edes muistaa.
- aivan kaikessa täytyisi painottaa että ei tämä aina ihan näinkään ole - tämä on vasta johdatusta.
 
Esimerkiksi BASH:in matematiikkaa ei käytetä ollenkaan koska siitä on tehty tarkasti harkituin toimenpitein käyttökelvoton. Otetaanpa esimerkiksi matriisin jäsenten keskiarvon laskeminen - aletaan helposta ja lasketaan aluksi se keskiarvo positiivisista kokonaisluvuista. Laskussa kaksi osaa: lukujen summaaminen ja keskiarvon laskeminen jakamalla summa kokonaislukujen lukumäärällä.

Tehdään matriisi jossa on 10000 suurehkoista satunnaisluvuista tehtyä jäsentä ja esitetään kolme tapaa saada niistä summa (skriptiä ajaakseesi leikkaa koko koodikenttä kerralla ja liimaa se pääteeseen ja paina return):
Koodia: [Valitse]
unset matrix; for n in {1..10000}; do matrix[$n]=$SRANDOM; done; echo ${matrix[@]}; echo

time { sum=0; for n in {1..10000}; do sum=$(($sum+${matrix[$n]} )); done; echo $sum ;}                     # se tapa mitä normaalisti käytetään - normaalinopea
time { sum=$(($(echo ${matrix[@]} | tr ' ' + ))); echo $sum ;}                                             # supernopea
time { sum=$(($(declare -p matrix | tr '"' '\n' | grep -E '^[0-9]' | tr '\n' + ; echo 0 ))); echo $sum ;}  # hypernopea
- eihän varsinkaan tuota hyperiä kannata koodiinsa kirjoittaa vaan semmoiset kuuluvat kirjastoon. Virtuoosit toisaan tiesivät kuinka kieli nitistetään - ei tarvitse tehdä muuta kuin antaaa 'kirjastokielto' - eikä senjälkeen kukaan halua nähdä vaivaa löytääkseen mitään parempaa koska se kumminkin vaipuu unhoon kirjastojen puuttuessa.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 13.03.24 - klo:06.33

Lasketaanpa siten keskiarvo. Keskiarvo on useimmiten desimaaliluku joten se vaatii laskuun omaa pitkähköä funktiotaan. Ajaakseesi laskun leikkaa liimaa koko koodikenttä päätteeseen ja paina return.
Koodia: [Valitse]

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##*.}; int1=${luku1%%.*}; int2=${luku2%%.*}

# desimaali-osat yhtäpitkiksi:
(( ${#desimaaliosa2} >= ${#desimaaliosa1} )) &&
{ apu=$desimaaliosa1"00000000000000000000"; desimaaliosa1=${apu:0:${#desimaaliosa2}} ;} || { apu=$desimaaliosa2"00000000000000000000"; desimaaliosa2=${apu:0:${#desimaaliosa1}} ;}
$tulosta koko1:$int1$desimaaliosa1'  koko2:'$int2$desimaaliosa2

# kokonais-osat yhtäpitkiksi:
(( ${#int2} >= ${#int1} )) &&
{ apu="00000000000000000000"$int1; int1=${apu: -${#int2}} ;} || { apu="00000000000000000000"$int2; int2=${apu: -${#int1}} ;}

luku1=$int1$desimaaliosa1;luku1=$((10#$luku1)); luku2=$int2$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 mitä numeroita tulokseen tulee:
unset tulos # vain varmistus että kaikki on tuloksessa tämänjälkeen uutta
luku1=$luku1'0000000000000000000'; luku1=${luku1:0:18} ;$tulosta " "$luku1 #"  "${#apu2}"  "$apu

for n in {1..2}; do # muodostetaan tulos-palasia 9 merkkiä kerrallaan
apu=$(($luku1/$luku2)); (( ${apu: -1} )) || apu=$apu'0';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..2}; do # kootaan tulosta matriisin palasista
uudetmerkit=${#tulos[$n]}; [[ $uudetmerkit -lt $vanhatmerkit ]] && tulos[$n]=$nolliatulosteessa${tulos[$n]} ; vanhatmerkit=$uudetmerkit
tulos=$tulos${tulos[$n]}
done
 
echo -e '\n'; [[ $nolliatulosteessa ]] && echo -n .$nolliatulosteessa${tulos:0} || echo -n ${tulos:0:$kokonaisiatulosteessa}.${tulos:$kokonaisiatulosteessa}
#bc<<<"scale=$((${#tulos}+$((${#nolliatulosteessa})))); $1/$2" | tr -d '\\\n'; echo '  tämä rivi on oikea tulos bc:stä' ;
}

unset matrix; for n in {1..12345}; do matrix[$n]=$SRANDOM; done; echo ${matrix[@]}; echo
sum=$(($(declare -p matrix | tr '"' '\n' | grep -E '^[0-9]' | tr '\n' + ; echo 0 )))
echo 'matriisin jäsenten summa='$sum'  ja jäsenien lukumäärä='${#matrix[@]}
time { keskiarvo=$( jaa $sum ${#matrix[@]}); echo; echo keskiarvo=$keskiarvo ;} # muissa kielissä koko skripti olisi vain viittaus kirjastoon ja lyhyt versio tästä lauseesta.

- eihän tämä skripti ole tarkoitettu käytettäväksi sillä onhan tämä hirveän monirivinen - lisäksi tämä on hidas muihin kieliin verrattuna vaikka BASH-skriptiksi todella nopea. Mutta sikäli mielenkiintoinen skripti että minkä takia opetetaan kelvotonta skriptaamista?   
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 16.03.24 - klo:12.13
Tehdäänpä esimerkki desimaalisten matriisien summaamisesta. Aluksi määritellään matriisi:
Koodia: [Valitse]
unset matriisi  # matriisit kannattaa ennen määrittelyä nollata
matriisi=($(seq -s' ' 9.9 -1.1 1 | tr , . ))
matriisi2=($(seq -s' ' 1.1 1.1 10 | tr , . ))
matriisi+=(${matriisi2[@]}) # tässä liitetään matriisit siten että kokonaisuuden nimeksi jää nimi: matriisi.
# sekoitetaan hieman pakkaa elikä kokeillaan kajahtaako muutos lopputulokseen oikein kun lisätään yhten matriisin jäsenistä .01 (oikea lopputulos on silloin 99.01)
matriisi[5]=4.41
echo katsotaanpa millainen matriisi aikaansaatiin:
printf "%s\n" "${matriisi[@]}"; echo

# sitten lasketaan matriisin jäsenten summa - ajoittaen lasku:
time { # matriisi täytyy jakaa desimaali-matriisiisiin ja kokonais-matriisiin sekä määritellä desimaali-matriisin pisin jäsen. Lopuksi desimaali-matriisin jäsenien loppuun laitetaan niin monta nollaa että jokaisen pituus on yhtämonta merkkiä:
desmatriisi=($(echo ${matriisi[@]##*.})); desmatriisinpisin=$(($(echo -e ${desmatriisi[@]/%/\\n} | wc -L)-1)); echo 'desimaaleja eniten: '$desmatriisinpisin; desmatriisi=($(printf "%.17f " ${desmatriisi[@]} | tr ' ' '\n' | tr -d , | cut -c -$desmatriisinpisin)); echo desijono=${desmatriisi[@]}; kokomatriisi=($(echo ${matriisi[@]%%.*})); echo kokojono=${kokomatriisi[@]}

# sitten lasketaan desimaali- ja kokonaismatriisien summat.
desisum=$(($(declare -p desmatriisi | tr '"' '\n' | grep -E '^[0-9]' | tr '\n' + ; echo 0 ))); echo desisum=$desisum' josta kokonaisiin lisätään: '${desisum:0:$((${#desisum}-$desmatriisinpisin))}' ja desimaaaleihin jää: '${desisum:$((${#desisum}-$desmatriisinpisin))}
kokosum=$(($(declare -p kokomatriisi | tr '"' '\n' | grep -E '^[0-9]' | tr '\n' + ; echo 0 ))); echo kokosum=$kokosum

# kokonais-summaa laskettaessa siirretään desimaaliosan ylivuoto kokonaisosan summaan:
kokosumma=$(($kokosum+${desisum:0:$((${#desisum}-$desmatriisinpisin))})); echo 'matriisin jäsenien summa='$kokosumma.${desisum:$((${#desisum}-$desmatriisinpisin))}
}

- skripti aikaansaa seuraavan tulosteen:
katsotaanpa millainen matriisi aikaansaatiin:
9.9
8.8
7.7
6.6
5.5
4.41
3.3
2.2
1.1
1.1
2.2
3.3
4.4
5.5
6.6
7.7
8.8
9.9

desimaaleja eniten: 2
desijono=90 80 70 60 50 41 30 20 10 10 20 30 40 50 60 70 80 90
kokojono=9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9
desisum=901 josta kokonaisiin lisätään: 9 ja desimaaaleihin jää: 01
kokosum=90
matriisin jäsenien summa=99.01

real   0m0,014s
user   0m0,015s
sys   0m0,010s

- tietysti ajat vaihtelevat aika paljonkin ajo-kerasta toiseen mutta suuntaus on niissä sama: koska user on yleensä tällä skriptillä paljonkin suurempi kuin real niin ilmeisesti kahdenkilon kalakukko on pistetty yhden kilon pussiin. Sitten on vielä sys-aika joka on merkittävän suuri sekin - tuntuu pussi ainavaan venyvän
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 18.03.24 - klo:07.13
- on mielenkiintoista seurata kuinka nämä viritykseni hiljokseen vuotavat kansainvälisille foorumeille. Ja kohta näitä aletaan syöttää tänne takaisin sikäläisinä huomiona.

Desimaalisen matriisin jäsenten summa kun mukana saattaa olla negatiivisia jäseniä:
Koodia: [Valitse]
# ensiksi määritellään esimerkki-matriisi joka arvoja lasketaan:
unset matriisi # Jos matriisille on joitain vanhoja määrittelyjä niin aluksi ne poistetaan.
matriisi=($(seq -s' ' 9.9 -1.1 1 | tr , . ))
matriisi2=($(seq -s' ' -1.1 -1.1 -10 | tr , . ))
matriisi+=(${matriisi2[@]}) # tässä liitetään matriisit siten että kokonaisuuden nimeksi jää nimi: matriisi.
# sekoitetaan hieman pakkaa elikä kokeillaan kajahtaako muutos lopputulokseen oikein kun lisätään yhteen matriisin jäsenistä .01 (oikea lopputulos on tällä matriisilla 0.01)
matriisi[5]=4.41
echo katsotaanpa millainen matriisi tälläkertaa aikaansaatiin:
printf "%s\n" "${matriisi[@]}"; echo # näin etukäteen muillatavoin laskettuna matriisin jäsenien summa on tälläkertaa siis: 0.01

# sitten lasketaan matriisin jäsenten summa - ajoittaen lasku:
time { # matriisi täytyy jakaa desimaali-matriisiisiin ja kokonais-matriisiin sekä määritellä desimaali-matriisin pisin jäsen. Lopuksi desimaali-matriisin jäsenien loppuun laitetaan niin monta nollaa että jokaisen pituus on yhtämonta merkkiä:
desmatriisi=($(echo ${matriisi[@]##*.})); desmatriisinpisin=$(($(echo -e ${desmatriisi[@]/%/\\n} | wc -L)-1)); echo 'desimaaleja eniten: '$desmatriisinpisin; desmatriisi=($(printf "%.17f " ${desmatriisi[@]} | tr ' ' '\n' | tr -d , | cut -c -$desmatriisinpisin)); echo desijono=${desmatriisi[@]}; kokomatriisi=($(echo ${matriisi[@]%%.*})); echo kokojono=${kokomatriisi[@]}
 
# täsävaiheessa täytyy ottaa huomioon se että mukana saattaa olla negatiivisia jäseniä. Asia oikeastaan on ihan yksinkertainen: kun negatiivinen luku jaetaan desimaalipisteen kohdalta niin merkki jää kokonaisosaan ja desimaaliosa jää aina positiiviseksi - mutta tämänkaltaisissa laskuissa kokonaisosan merkki kuuluu myös desimaaliosaan ja se täytyy siis oikaista:
for (( n=0; n<=${#matriisi[@]}; n++ )); do [[ ${matriisi[$n]:0:1} = \-  ]] && desmatriisi[$n]=-${desmatriisi[$n]}; done
echo 'Desimatriisista tuli kun merkit oikaistiin: '${desmatriisi[@]}
 
# sitten lasketaan desimaali- ja kokonaismatriisien summat. Onneksi BASH:in matematiikkamoottori ymmärtää että ilmaisu: +-  merkitsee samaa kuin: -
desisum=$(($(declare -p desmatriisi | tr '"' '\n' | grep -E '^[-0-9]' | tr '\n' + ; echo 10000000 ))); echo desisum=$desisum' josta kokonaisiin lisätään: '${desisum:1: -$desmatriisinpisin}' ja desimaaaleihin jää: '${desisum:$((${#desisum}-$desmatriisinpisin))} # 10000000 on vain varmistus siitä että myös0.01 toimii oikein - etuykkönen hylätään aina
kokosum=$(($(declare -p kokomatriisi | tr '"' '\n' | grep -E '^[-0-9]' | tr '\n' + ; echo 0 ))); echo kokosum=$kokosum

# kokonais-summaa laskettaessa siirretään desimaaliosan ylivuoto kokonaisosan summaan:
kokosumma=$(($kokosum+${desisum:1: -${desmatriisinpisin}})); echo 'matriisin jäsenien summa='$kokosumma.${desisum: -$desmatriisinpisin}
}

 
- tästä skriptistä selviää moni asia joista olisi oleellista apua useiden jo osittain ratkenneiden matemaattisten tehtävien oikeellistamisessa ja yksinkertaistamisessa, alkaen kuitenkin desimaalilukujen yhteenalaskusta.
- tätä matriisien summaamista voi muuttamatta mitään käyttää eksinkertaiseen yhteen/vähennyslaskuunn jossa jäseniä voi olla vain kaksi - tai ihan niin monta kuin haluaa - elikä kauppalasku ratkeaa samalla funktiolla kuin yksinkertainen ynnä-lasku tai todella iso matriisikin.
- ei tämä vielä moitteetonta ole vaan paljon tytyy vielä tehdä - mutta jos tämänkaltaisia virityksiä olisi alettu harrastaa jo silloin kolmekymmentä vuotta sitten  kun nämä periaatteessa toimivat jo niin tänäpäivänä meillä olisi esittää jotain tosi-pätevää, olisivat pythonitkin nesteessä.
- BASH on siitä mukava että jo etukäteen voi olla varma että mitä yrittääkin onnistuu varmasti - toisaalta on melkein yhtä varmaa että ennenkuin kaikki on oikein löydät lukemattomia sellaisia keinoja joissa on jotain moittimista. 
- BASH on tuhansia kertoja liian hidas jotta tästä olisi ohjelmallisesti mitään mieltä lähi-tulevaisuudessakaan - mutta pähkäily pitää pää-nuppia kunnossa ja antaahan se tyydytystä tehdä sellaista jota väitetään mahdottomaksi.
- kannattaa kokeilla matriisiksi: unset matriisi; for n in {1..12345}; do matriisi[$n]=$SRANDOM.$SRANDOM; done
- Mielestäni opetuksella on vain kaksi vaihtoehtoa - yritetään opettaa kunnolla tai ei opeteta ollenkaan. Mitä nuo 'advanced guidet' sönköttää?
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 18.03.24 - klo:12.22
Supernopea ja moitteeton desimaali- tai kokonaislukujen yhteen/vähennyslaskin - sen lopputuloksessa voi kylläkin olla numeroita vain 18:
- mutta jo 36 numeroinenkin yhteenlasku vaatii paljon lisää
Koodia: [Valitse]

function summain () {
[[ ${1//[^.]/} ]] && luku1=$1 || luku1=$1".0"
[[ ${2//[^.]/} ]] && luku2=$2 || luku2=$2".0" 
 
koko1=${luku1%%.*};
desi1=${luku1##*.};   
koko2=${luku2%%.*};
desi2=${luku2##*.}

# desimaaliosien tulee olla yhtäpitkät. Lyhyemmän perään kirjoitetaan nollia.
(( ${#desi1} >= ${#desi2} )) && desipituus=${#desi1} || desipituus=${#desi2}
desi1=$desi1'000000000000000000'
desi2=$desi2'000000000000000000'
desi1=${desi1:0:$desipituus} #; echo desi1:$desi1
desi2=${desi2:0:$desipituus} #; echo desi2:$desi2 ;$tulosta

luku1=$koko1$desi1
luku2=$koko2$desi2

tulos=$(($luku1+$luku2)); echo ${tulos:0: -desipituus}.${tulos: -desipituus} ;}

summain 31.1  1.1111111  # tämä on yhteenlasku
summain 31.1 -1.1111111  # tämä on vähennyslasku
summain -31.1 -1.1111111 # voi kummatkin negatiivisiakin olla
summain 1 1              # kannattaa varmistaa että tämmöinenkin toimii 

Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 19.03.24 - klo:17.03
Edellä esitetty desimaalilukujen yhteenlasku olisi pitänyt kasata jo yli kolmekymmentä vuotta sitten kun sen osat toimivat jo - tämä on jonkinverran erilainen kuin aikaisemmin esitetyt versiot kiertäen pari salahautaa. Enkä usko sekuntiakaan etteivät virtuoosit tienneet näistä mutta sensijaan että olisivat julkaiseet tällaisten koodeja alkoivatkin väittää tämmöisiä mahdottomiksi. Joten täytyy nyt esittää tämä koodi kun asialla ei ole enää mitään virkaa - mutta voi sentään toivoa että jatkoa löytyy. Mutta mielenkiinnon vuoksi tutkin toimiiko tämä aina oikein.

Näiden perus-laskutoimitusten skriptien toiminnan tulee olla nopeutensa lisäksi toimia aina virheettömästi joten toiminta on syytä tarkistaa. Tarkituksesta tulee käsipelillä tosihidasta, mutta täysin automaattinen tarkistus loisi tässävaiheessa uskottavuus-ongelmia - joten aluksi tehokas puoli-automaattinen ratkaisu - jossa näkee jonkunverran siitä mitä tapahtuu.

Aluksi vain täytetään koko näyttö tuloksista. Tulostukset tulevat aina pareittain, ensin tulee arvo bc:stä ja se on ihan varmasti oikein - sen alapuolelle tulee tämän skriptin aikaansaannos ja sitten tyhjä rivi. Tarkoitus on siis varmistaa että lukuparissa kumpikin on sama.

Ajaakseesi skriptin kopioi koko koodikenttä kerralla ja liimaa se päätteeseen ja paina return jolloni tulee 20 tulosta - kun näyttö jähmettyy niin näkee heti onko jollain ryhmällä luvut erilaisia - ja jos on niin koodi on viallinen joten varmasti ei ole - mutta itse se on todettava. Kun painat nppulaa 'nuoli-ylös' palaa kutsu takaisin näytölle ja return saa aikaan 20 uutta laskua.

- kutsuttuasi kutsun takaisin voit editoida sitä ja poistaa kutsusta miinusmerkin joten vähennyslasku muuttuu yhteenlaskuksi.
elikä tämmöiseksi: for n in {1..20};do summain $RANDOM.$RANDOM $RANDOM.$SRANDOM; done .
Koodia: [Valitse]
function summain () {
echo; bc -l<<<"$1+$2" # jos kutsu on vähennyslasku niin laskuun tulee +- ja sekä BASH että bc tajuavat että se on - . Sensijaan merkintää: -- ne eivät ymmärrä.
[[ ${1//[^.]/} ]] && luku1=$1 || luku1=$1".0"
[[ ${2//[^.]/} ]] && luku2=$2 || luku2=$2".0" 
 
koko1=${luku1%%.*}
desi1=${luku1##*.}   
koko2=${luku2%%.*}
desi2=${luku2##*.}

# desimaaliosien tulee olla yhtäpitkät. Lyhyemmän perään kirjoitetaan nollia.
(( ${#desi1} >= ${#desi2} )) && desipituus=${#desi1} || desipituus=${#desi2}
desi1=$desi1'000000000000000000'
desi2=$desi2'000000000000000000'
desi1=${desi1:0:$desipituus} #; echo desi1:$desi1
desi2=${desi2:0:$desipituus} #; echo desi2:$desi2 ;$tulosta

luku1=$koko1$desi1
luku2=$koko2$desi2

tulos=$(($luku1+$luku2)); echo ${tulos:0: -desipituus}.${tulos: -desipituus} ;}

for n in {1..20};do summain $RANDOM.$RANDOM -$RANDOM.$SRANDOM; done
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 23.03.24 - klo:18.42
BASH:in pahin piirre on sen tajuton monipuolisuus ja se että salahautojen välissä on vain vähän tukevaa maata - lisäksi BASH-toteutuksia on melkein yhtämonta kuin erilaisia Linuksejakin - ja kaikki tekevät omia virityksiään - luulisinpa että joku tuhoaa Linuksiakin eikä vain BASH:ia. Nimittäin kielikin tuhotaan parhaiten sisältäpäin - IBM, Windows ja Mac:kin ovat osallistuneet karkeloihin - tahallaan vai tarkoituksella?

Mutta BASH:ista puhuakseni: kun lähestyin isojen lukujen kahdella jakamista toista reittiä kuin ennen niin havaitsin että esimerkiksi lasku: 12345678901234567890123456780876/2 lasketaaan BASH:illa näin:
Koodia: [Valitse]
echo $((12345678901234567/2))$((10#$((12345678901234567%2))890123456780876/2))   
ämä on jatkoa sille että matematiikkamoottorille voi lähettää millaista törkyä tahansa ja se yrittää selittää sen parhainpäin - tottamaar sen täytyy noudattaa tiettyjä määräyksiä. Mutta jos kuvatusta muodosta tekee skriptin:
Koodia: [Valitse]
echo $(($a/2))$((10#$(($a%2))$b/2))

elikä siinä alle 32 numeroinen luku on katkaistu suurinpiirtein keskelta ja a on se etuosa ja b on takaosa. Mutta lasku ei valitettavasti toimi oikein kaikilla a:n ja b:n arvoilla, useimmilla kylläkin - ja syystä ei vielä ole aavistustakkaan. Eikä ole minkäänlaista varmuutta että siitä koskaan saa tehtyä mitään todella käyttökelpoista - se on kyllä selvinnyt että itseasiassa se kelpaa alle 32 numeroisten kokonaislukujen jakamiseen kaikilla alle 16 numeroisilla - tulos on kylläkin kokonaisluku, ihan niinkuin ennenkin - jakojäännöksineen. Kai tätäkin toimintaa kannattaa tutkia vaikkei siitä enää muuta hyötyä ole kuin muinaisten virtuoosien kiemurtelu.
Otsikko: Vs: Skriptiajuri
Kirjoitti: petteriIII - 28.03.24 - klo:09.48
Matemaattista yhtäsuuruuden vertaamista ei kannata tehdä matemaattisesti sillä se rajoittaisi merkkiluvun 18:sta eivätkä  desimaalit toimisi ollenkaan - siksi on parempi suorittaa vertailu tekstijonoilla.

Tekstijono-vertailu on nopea mutta se toimii melkein aina virheellisesti desimaalien kanssa, sillä vertaaja ei tajua että desimaalit tulee verrata merkki kerrallaan alkaen desimaalipisteestä ja heti kun toinen on erilainen niin vertailu lopetetaan desimaalien osalta sillä voittaja on löytynyt - desimaalit voi kyllä verrata tehokkaasti ryhmänäkin mutta silloin lyhyemmän desimaaliryhmän perään tulee kirjoittaa niin monta nollaa että pituudet ovat samoja - tässä skriptissä käytetään tätä tehokkaampaa tapaa.

Samoin tekstijono-vertailu menee usein pieleen etumerkkien kanssa. Tässä asia hoidetaan erikseen.

Tekstijono-vertailu ei kavahda tekstiäkään vaan voit kirjoittaa: kumpionsuurempi 12km/t 13km/t

Aikaa vertaamiseen kuluu tällä skriptillä noin 1 ms riippumatta siitä millaisia lukuja verrataan.

Ja ennenkaikkea tälle skriptille olisi helppo opettaa uusia temppuja, esimerkiksi tieteellisesti esitettyjen lukujen vertailu, merkkimuutoksien tekeminen tai matematiikan suorittaminen ennen vertailuja ... Mutta tämänhetken toiminta:
 
1. Lukujen etumerkit talletetaan omiin muuttujiinsa.
2. Jos toinen tai kumpikin luvuista on pelkkä kokonaisluku niin sen desimaaleiksi kirjoitetaan .0   
3. desimaaliosista tehdäänyhtäpitkätkirjoittamalla lyhyemmän perään nollia.
4. jos toinen tai kumpikin luvuista on pelkkä desimaaliluku niin kokonaisosaksi kirjoitetaan .0   
5. kokonais- ja desimaaliosa kirjoitetaan peräkkäin jättäen desimaalipiste pois.
6. suuremmuuden testaus suoritetaan tekstijono-vertailuna. Tämä on melkein yhtänopea kuin erittäin rajoittunut matemaatinen vertailu BASH:in matematiikalla - ja paljon nopeampi kuin vertailu bc:llä.

- miten toiminta koodataankin niin käskyissä ei ehdottomasti saa olla yhtäkään uutta käskyä - ne on tehty tuhoamaan BASH:in nopeus - on syytä epäillä että tuhoaminen tehtiin tarkoituksella eikä tapahtunut  vahingossa.
- mikähän kaikki muukin olisi mahdollista kun BASH pystyy tällaiseen vielä kolmenkymmenen vuoden heitteillejätön jälkeen? Mutta jokatapauksessa kestää vielä kauan näiden skriptien vakautumiseen sillä oppirahat on aina maksettava.

Koodina tämä on tällainen:
 
Koodia: [Valitse]
function kumpionsuurempi () {
[[ $1 =~ .*\..* ]] && luku1=$1 || luku1=$1".0" # on tarpeen että luvussa on yksi desimaalipiste - joten piste lisätään luvun perään sellaista jos ei vielä ole.
[[ $2 =~ .*\..* ]] && luku2=$2 || luku2=$2".0"
[[ ${1//[^-]/} ]] && m1=- || m1=+; [[ ${2//[^-]/} ]] && m2=- || m2=+ # lukujen merkit omiin muuttujiinsa - mutta ei niitä etumerkkejä poistaa tarvitse
 
koko1=${luku1%%.*};koko2=${luku2%%.*};koko1=${koko1:=0} ;koko2=${koko2:=0}     # käskyssä: koko2=${koko2:=0} -> 0 on oletusarvo jos mitään ei aikaisemmin ole

desi1=${luku1##*.}; desi2=${luku2##*.} 

# desimaali-osat yhtäpitkiksi:
(( ${#desi2} >= ${#desi1} )) &&
{ apu=$desi1"00000000000000000000000000"; desi1=${apu:0:${#desi2}} ;} || { apu=$desi2"00000000000000000000000000"; desi2=${apu:0:${#desi1}} ;}
luku1=$koko1$desi1; luku2=$koko2$desi2 # muutos

[[ $luku1 = $luku2 ]] && echo 'luvut ovat yhtäsuuria' || {
case $m1$m2 in
-+) echo 'toka on suurempi' ;;
+-) echo 'eka on suurempi' ;;
++) [[ $luku1>$luku2 ]] && echo 'eka on suurempi' || echo 'toka on suurempi' ;; # tai tulostus tosikäytössä: 'eka on suurempi' kirjoitetaan: 1 - ja 'toka on suurempi' kirjoitetaan: 0
--) [[ $luku1>$luku2 ]] && echo 'toka on suurempi' || echo 'eka on suurempi' ;;
esac ;};}

time kumpionsuurempi 7C12.5B 7C12.5C1234567890 # siis hexa-desimaali lukujen vertailu

# tai vertailtavissa voi olla niin paljon numroita etteivät ne mahdu yhdelle riville:
time kumpionsuurempi 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890.1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567891