Kirjoittaja Aihe: Ohjeita shell-skriptaukseen (bash)  (Luettu 377153 kertaa)

Antifilatelisti

  • Käyttäjä
  • Viestejä: 258
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #60 : 06.05.11 - klo:00.45 »
Olinpas hölmö.

Hommahan menee melkein samalla tavalla kuten ennenkin. Hieman muunnettu petterillin alkuperäisestä versiosta:

  • 1.Napsauta tyhjää työpöytää->luo käynnistin
1.1 Tyyppiin valitaan sovellus päätteessä
1.2 Nimeen laitetaan vaikkapa omakomento
1.3 Komentoon selaat oman komennon
  • 2.0 Valitse tekemäsi kuva kuvakkeeksi napsauttamalla oheista "vieterilautaa"
  • 3.0 Siirrä työpöydälle syntynyt kuvake vaikkapa kuvat kansioon
  • 4.0 Raahaa kuvake kuvat kansiosta paneliin.

« Viimeksi muokattu: 06.05.11 - klo:00.47 kirjoittanut Antifilatelisti »

BackTrack

  • Käyttäjä
  • Viestejä: 1
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #61 : 28.05.11 - klo:00.11 »
Hei,

ei ole näitä scriptejä tullut tehtyä, niin neuvot olisivat paikallaan. Jonkun yksinkertaisen saisin varmasti itsekkin tehtyä, mutta tämä nyt ei ainakaan omassa pääkopassa kovin yksinkertaiselta tuntunut, eikä noilla suomenkielisillä ohjeistuksilla mitä webistä löysin oikein saanut kiinni asiasta. Kysyn siis suosiolla kokeneemmilta :)

Eli tarvitsisi saada scripti seuravaanlaiseen toimintaan.

Kansiossa X on useita tekstitiedostoja. Tiedostot on nimetty jotenkuten loogisesti, mutta ei aivan "tiedosto1.txt", "tiedosto2.txt" jne. tyylisellä kurinalaisuudella.

Tekstitiedostoista on suurin osa turhia, mutta noiden sisällön kahlaaminen käsin on aikaa vievää ja turhauttavaa touhua. Ajatus olisi siis saada scripti joka kävisi tiedostot läpi, suorittaisi jokaisessa tiedostossa haun määritellyllä sanalla/sanoilla/numerolla/virkkeellä ja mikäli vastaavuus tiedostosta löytyy, siirtäisi sen toiseen kansioon/nimeäisi eri tavalla tai jättäisi ne tiedostot rauhaan joista vastaavuus löytyy, mutta poistaisi suoraan tiedostot joista vastaavuuksia ei löydy.

Onko tälläinen edes mahdollinen?  ::)

Eli jos ajateltaisiin asiaa siltä kantilta, miten itse tuon käsin tekisin, menisi se jotenkuten näin: Kansio auki, tekstitiedosto auki, ctrl+f  ; hae sanaa/virkettä/numeroa. If vastaavuus löytyy = tiedosto talteen, else = tiedosto roskiin. Seuraava tiedosto auki, haku, roskiin/talteen, seuraava tiedosto auki, haku, roskiin/talteen jne.jne.jne.. Ja tämä pitäisi nyt saada kirjoitettua scriptiksi, sillä noita tiedostoja on tosiaan vähän liikaa näin käsin kahlattavaksi..

Erittäin suuret kiitokset auttajille, jo näin etukäteen :)
« Viimeksi muokattu: 28.05.11 - klo:00.14 kirjoittanut BackTrack »

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #62 : 28.05.11 - klo:14.13 »
Lainaus
Onko tälläinen edes mahdollinen?

No varmasti.   Sen sijaan että antaisin valmiin ratkaisun heti niin annan pieniä ideoita joista pääsee alkuun kokeilemaan.  Pikkuisen "rautalankaa" teemasta aluksi.


ls  näyttää tiedostojen nimet

cat  teksti.txt  tulostaa tiedoston sisällön

grep jotain_tekstiä  valitsee vain ne rivit joilla esiintyy jotain_tekstiä


Komentoja voi "putkittaa" peräkkäin käyttämällä "putkimerkkiä":   |      Tuo putkittaminen tarkoittaa että sen sijaan että komennon tulokset menisi näytölle ne meneekin toiselle komennolle.  Esimerkki:

ls | grep txt

näyttää kaikki joissa esiintyy "txt".  Komennon "ls" tulokset menevät ohjelmalle "grep" joka seuloo halutut rivit.  Vastaavasti  

ls | grep -v txt

näyttää kaikki joissa ei esiinny "txt"   (eli tuo -v  kääntää merkityksen).  Tuolle "grep" seulalle pystyy antamaan tiedoston joka sisältää ne kaikki halutut osumat omilla riveillään.  Tällöin yllä oleva komento saa muodon:

ls | grep -f lista.txt

Tuonne "lista.txt" kirjoitellaan editorilla (gedit lista.txt)  ne sanat tai lauseet jotka halutaan löytää, kukin omalle rivillensä.  Tyhjiä rivejä ei saa jäädä minnekään yhtä ainutta, ei edes tiedoston loppuun tai tuo seula ei toimi.

Näitä on helppoa kokeilla päätteessä.  Jos ei selviä putkittamalla kaikki komennot peräkkäin yhdelle riville niin aina voi tehdä komentotiedoston (scripti) mihin laittaa komentoja peräkkäin kunnes koko asia onnistuu.    Tiedoston nimellä ei ole merkitystä mutta tietysti auttaa myöhemmin muistamaan mikä tämä on jos antaa kuvaavan nimen.  Jos tiedoston tyypiksi antaa "bash" niin se jo kuvaa käyttötarkoitusta.  Tiedoston ensimmäisellä rivillä pitää lukea risuaita huutomerkki /bin/bash ja komennot peräkkäin sen jälkeen.  

Koodia: [Valitse]
#!/bin/bash
komentorivi_1
komentorivi_2
jne.
Tuolle tiedostolle pitää erikseen sallia oikeus ajaa sitä kometotiedostona:

chmod +x komentotiedostoni.bash

Tuon jälkeen sen voi ajaa:
Koodia: [Valitse]
./komentotiedostoni.bashÄlä unohda tuota "piste-ja-kauttaviiva" -yhdistelmää edestä, tarkoittaa nykyistä hakemistoa.

Tässä on lyhyt listaus komennoista joita voi tuonne viritellä:

http://ss64.com/bash/

Sitten vaan kokeilemaan. Ja korjaamaan..  :)


« Viimeksi muokattu: 28.05.11 - klo:14.19 kirjoittanut ajaaskel »
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #63 : 29.05.11 - klo:20.44 »
Menihän tuo yhdelle riville.  Tässä lyhyt ohje:

1)  Tee kotihakemistoosi editorilla tiedosto jonka nimi on "lista".  Laita tuohon tiedostoon kaikki ne sanat tai sanonnat joita etsit omista tekstitiedostoistasi, kukin omalle rivillensä.   Älä jätä tyhjiä rivejä minnekään, ei alkuun eikä loppuun.  Viimeisen rivin pitää loppua viimeiseen kirjaimeen, siellä ei saa olla "Enter": iä perässä !  

Koodia: [Valitse]
gedit ~/lista
2) Siirry hakemiston alle jossa tekstisi sijaitsevat.

3)  Testaa tekemäsi tiedoston toiminta tällä, se näyttää vain niiden tiedostojen nimet joista tuli osuma (eli jotka halutaan siirtää talteen):

Koodia: [Valitse]
grep -Hs -f lista *.txt | cut -d ":" -f1  

Jos tuntuu että jotain tärkeää puuttuu niin käy uudestaan kohdassa 1 ja testaa uudestaan.

4) Kaikki ok ?  Sitten menoksi:

Koodia: [Valitse]
mkdir backup && grep -Hs -f ~/lista *.txt | cut -d ":" -f1 | xargs -r -n 1 -I{} mv {} ./backup
Tuo tekee ensin "backup" -hakemiston samaan paikkaan minne olit siirtynyt "cd": llä ja siirtää valitut tiedostot sinne.  Ylläolevassa on oletettu että tiedostot ovat *.txt.  Samassa hakemistossa ei saa olla "/backup" -hakemistoa valmiina tai ylläoleva rivi ei tee mitään (varotoimi).

Tässä on vielä ylläolevasta "tekee eikä huomauttele" -versio, yrittää luoda "/backup" -hakemiston mutta ei keskeytä jos se jo oli olemassa vaan jatkaa tiedostojen siirtoon:

Koodia: [Valitse]
mkdir backup 2>/dev/null ; grep -Hs -f ~/lista *.txt | cut -d ":" -f1 | xargs -r -n 1 -I{} mv {} ./backup
« Viimeksi muokattu: 29.05.11 - klo:21.28 kirjoittanut ajaaskel »
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

VilhoPamppu

  • Käyttäjä
  • Viestejä: 58
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #64 : 01.06.11 - klo:18.45 »
Onko olemassa tai olisiko mahdollista luoda scriptiä joka:

käyttäisi web-kameraa ja ottaisi kuvan jos kirjautuessa käyttäjätilille tulisi väärä salasana, tallentaisi sen paikkaan x tahi lähettäisi verkon yli palvelimelle x.

En ole oikeastaan vielä juurikaan tutustunut scriptaukseen notta mietin olisiko tässä projekti jolla aloittaa.

Eli jos aloittais sillä että tallentaisi kuvan koneelle (jättäisi tuon verkon yli sitten myöhemmäksi  :D) niin mistähänä kannattaisi aloittaa (jos saisi vinkkiä edellisten viestien tapaan)  :)

1) koneen käynnistyessä aja scripti
2) if salasana väärin jatka scriptiä
  3) käynnistä muikku ja ota kuva
  4) tallenna kuva
  5) lopeta looppi ja palaa kohtaan 2)
6) else lopeta scripti

vai onko jo ajatusmalli päin honkia?

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #65 : 03.06.11 - klo:02.03 »
Ei tuokaan mikään mahdoton ole. Vaikein kohta saattaa olla tuo epäonnistunut login.  Koko idea pitäisi saada viritettyä niin päin että tuo scripti ajetaan epäonnistuneen loginin avulla.   Joku ehkä tietää miten epäonnistuneeseen loginiin voisi lenkittää oman scriptin kiinni.
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #66 : 03.06.11 - klo:15.26 »
Törmäsin verkossa käskyyn: cheese --snapshot --delay 1 --outfile $HOME/Pictures/failedlogin.jpg
joten joku on ilmeisesti saanut homman toimimaan.

Tulee montakin hommaa mieleen: mikä $HOME kun ei vielä olla kirjauduttukaan?

Onkohan ratkaisu sopiva vain kokoajan toiminnassa olevaan isoon serveriin ? Mutta toisaalta BASH kyllä kykenee mihin hyvänsä.
   
« Viimeksi muokattu: 04.06.11 - klo:10.35 kirjoittanut petteriIII »

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #67 : 04.06.11 - klo:18.48 »
Lainaus
Onko olemassa tai olisiko mahdollista luoda scriptiä joka:

käyttäisi web-kameraa ja ottaisi kuvan jos kirjautuessa käyttäjätilille tulisi väärä salasana, tallentaisi sen paikkaan x tahi lähettäisi verkon yli palvelimelle x.

Selasin hieman asiaa netistä. Scripti joka käynnistyy heti kun käyttäjä antaa väärän salasanan tuntuu aika vaikealta toteuttaa.  Paikka jossa tiedetään tuliko oikea vai väärä salasana on "PAM" mutta tuota ei taida saada asetettua (?) käynnistämään mitään scriptiä.  PAM: iin pitäisi tehdä oma moduli. 
Asiaa voi kiertää (erittäin tehottomalla tavalla) käymällä läpi lokitiedostoa usein ja reagoimalla "FAIL" -viestiin. Lisäksi on olemassa "pam-hooks" -ohjelma joka voi käynnistää scriptejä aina kun login aktivoituu (en tutkinut tuota tarkemmin).

Jos joku tietää miten PAM: in saa viritettyä käynnistämään scriptin epäonnistuneen loginin tilanteessa niin kiinnostaa toki kuulla.
 
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #68 : 20.06.11 - klo:19.32 »
Kummitteleva "CD 84

Olen pariin otteeseen törmännyt outoon ongelmaan Gedit: in kanssa:  Jostain ilmestyy ylimääräiset heksakoodit "CD 84" jotka eivät näy Gedit: ssä mitenkään mutta sotkevat kometotiedoston toiminnan kokonaan.   
Samoin kävi nyt tuon "petteril": in ohjelmanpätkän kanssa kun siirsin sen Gedit: iin, tallensin nimellä "aaa", annoin ajo-oikeuden ja yritin käynnistää:

  chmod +x aaa

  ./aaa
  bash: ./aaa: /bin/basḧ́: bad interpreter: No such file or directory

  ls aaa
  aaa

 Onneksi oli heksaeditori käsillä (Bless) joka näytti ongelman laadun.   Sitä ennen ehdin jo ihmetellä tovin enkö osaa bash: iä enää pätkääkään  :)


[ylläpito on poistanut liitteen]
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #69 : 25.06.11 - klo:18.00 »
 Skripti toimii naurettavan hitaasti jopa BASH skriptiksi johtuen siitä että mitään skriptiä ei edes ole vaan pääte itse toimii laskimena. Lisäksi BASH:in on pakko käyttää laskentaan jotain laskin-ohjelmaa. Ja laskinohjelmat ovat matemaatikoille tarkoitettuja ja niiden merkintätavat senmukaisia. Tämä skripti käyttääkin ajastaan valtaosan muuttaakseen merkintätavat inhimillisiksi. Jos haluaa skriptiinsä BASH:in normaalia nopeutta kannattaa tästä skriptistä kopioida omaan skriptiin tarvittava osa - siis tämä skripti vain osoittaa mikä on mahdollista.

Käyttääkseesi päätettä laskimena kopioi seuraaava koodi johonkin tiedostoon koneessasi. Kun avattuasi päätteen annat käskyn:  . polku_tiedoston_nimeen (siis: piste välilyönti polku) niin kehote tulee takaisin semmoisenaan ja tuntuu siltä ettei mitään tapahtunut. Mutta vaikka pääte toimii niinkuin ennenkin niin tämä pääte osaa nyt normaalin pääte-toiminnan lisäksi toimia myös laskimena - jos esimerkiksi kirjoitat päätteeseen: sin30-cos60 niin enteriä painettuasi saat vastauksen: -.000000000000000000000000000000000000000000000000000000000000000003  . Listan tunnetuista laskuista saat käskyllä: laske. Skripti ei tee koneeseen mitään pysyviä muutoksia ja kun suljet päätteen niin matematiikka-taidotkin unohtuvat.

Laskimella on hitautensa korvauksena rajoittamaton tarkkuus:
- jos haluat laskustasi tuhansia oikeita desimaaleja niin se onnistuu.
- kokonaisosan numeromäärää ei rajoiteta koskaan. Esimerkiksi 10000!:n kaikki 36000 numeroa lasketaan 3:ssa sekunnissa.
- myös samassa päätteessä toimivat skriptit perivät matemaattiset taidot.
- toiminta alkaa siitä että kirjoitetaan päätteeseen "laskukaava" ja painetaan enter. Mikäli funktiot eivät osaa laskukaavaa toteuttaa siirretään "laskukaava" päätteen komento-tulkille joten normaali päätetoiminta on mahdollista.

Koodia: [Valitse]
#!/bin/bash
# petteriIII 2.7.2014 ~/OMATSKRIPTIT/FUNKTIOKIRJASTO/matemaattiset_funktiot
set +H # jos tämä puuttuisi niin kertoman merkki: ! aiheuttaisi virheen
unset command_not_found_handle # poistaa virheviestit mallia: tarkoititko käskyä xxx paketissa yyy


trap 'laske "$BASH_COMMAND"' 1 ERR

function laske () { # Tuloparametrina on laskukaava. Tulostaa näytölle ja asettaa kutsuttujen funktioiden nimiset muuttujat ja tuloksen muuttujaan: tulos.
[[ ! $1 ]] && echo "- laskuissa on 66 desimaalia jollei toisin määrätä. Desimaalipisteen jälkeisiä peränollia ei tulosteta.
- kokonaisosan numeromäärä on aina rajoittamaton ja desimaalien määrän voi määrätä ihan miksi haluaa.
- sallitut operaattorit: +, -, *, / ja ^ Näissä laskuissa ^ on potenssiinkorotus, esimerkiksi 3^0.5  tai: 10000000000^-0.1.  
- funktiot: sin, asin, cos, tan, atan, sqrt, log, ln, exp, abs, int, e, pi, ! (=kertoma), kahteen, kymmeneen (kantaluvun muutokset), des (määrää desimaalien
  luvun),  rad (=määrää että geometriset laskut suoritetaan radiaaneissa), annuiteettilaina lainanmäärä korkoprosentti lainaaika_vuosissa -> vuosilyhennys
- merkitätavat noudattavat normaaleja matematiikan sääntöjä. Sulkuina on kuitenkin helpointa käyttää hakasulkuja.  
- syötettävien esitysmuoto voi olla tieteellinenkin, esimerkiksi: 1.23e6 . Vaikka se olisi samassa lauseessa kuin joku luonnollisen e:n funktio.
- desimaalien ja radiaanien määräämis-esimerkki: des256radsin0.511 . Asetukset säilyvät kunnes muutetaan tai vaihdetaan päätettä.
- testilaskuja: -1-[2*6!+1]/1441+[[sin210-cos60]*tan60*2]/[3^.5]*ln[e^-pi]/pi -> 0 ; ln[e^ln[e^ln[e^ln[e^ln[e^ln[e^ln[e^ln[e^1.25]]]]]]]] -> 1.25 ;
  2+1.1e2+e-2.7 -> 110.018....; sin[asin.5]-asin[sin.5] -> 0
- edellisen laskun tulokseen voi viitata sanalla: tulos (esimerkiksi laskun: 3^-.5  tuloksen -oikeellisuustesti- on: 1/tulos joka on neliöjuuri 3)"

trap "" 1 ERR
tulos=$1

# testi yritetäänkö jotain tuntematonta:
[[ $(echo $tulos | sed 's/asin//g;s/sin//g;s/cos//g;s/atan//g;s/tan//g;s/log//g;s/ln//g;s/exp//g;s/sqrt//g;s/int//g;s/abs//g;s/kymppiin//g;s/kahteen//g;s/des//g;s/pi//g;s/annuiteetti//g;s/e//g;s/rad//g;s/ast//g;s/\!//g;s/tulos//g' | grep [a-zäöåA-ZÄÖÅ] ) ]] && exec $tulos
 

lasketaan_radiaaneissa=${lasketaan_radiaaneissa:-0} # toimintamuotona on asteet ellei toimintamuodoksi peritä radiaaneja.
desimaaleja=${desimaaleja:-66} # laskujen desimaaliluku on 66 ellei peritä toista arvoa.

tulos=${tulos#+}   # poistetaan + edestä
tulos=${tulos%%#*} # poistetaan kommentit
tulos=${tulos//tulos/$tulos} # muutetaan annetussa laskussa sana:tulos edellisen laskun muuttujaan tulos
tulos=$(echo $tulos | tr -d \' | tr -d \" | tr "(" '[' | tr ")" ']' ) # poistetaan heittomerkit ja muunnetaan kaarisulut hakasuluiksi.
tulos=$(echo "$tulos" | sed 's/--/+/g;s/++/+/g;s/-+/-/g;s/\^+/\^/g;s/\/+/\//g;s/\*+/\*/g') # -- muuntuu +:ksi ja /+ muuntuu /:ksi ja *+ muuntuu *:ksi
[[ $(echo $tulos | grep des) ]] && maaraa_laskujen_desimaaliluku
[[ $(echo $tulos | grep rad) ]] && lasketaan_radiaaneissa=1

# muutetaan luonnollisen järjestelmän kantaluku e lukuarvoonsa kaikkialla. Siis luvut kuten tuo e kaavassa: 1+e^2
e_numeroina=$(exp 1)
tulos=$(echo $tulos | sed "s/e$/$(exp 1)/g;s/^e/$(exp 1)/g" ) # muuttaa e:n rivin alusta ja lopusta
apu=$(echo $tulos | grep -ob [^0-9a-z]e[^a-z0-9] | tr "\n" " " | awk '{print $1}' )
while [[  $apu != "" ]] ; do e_paikka=${apu%%\:*}; tulos=${tulos:0:e_paikka+1}$e_numeroina${tulos:e_paikka+2}; apu=$(echo $tulos | grep -ob [^0-9a-z]e[^a-z0-9] | tr "\n" " " | awk '{print $1}' ); done

# muutetaan pi (ympyrän kehä/halkaisija) lukuarvoonsa kaikkialla
pi_numeroina=$(echo "scale=$desimaaleja; 4*a(1)" | bc -l | tr -d '\\' | tr -d "\n")
tulos=$(echo "$tulos"  | sed "s/pi$/$pi_numeroina/g" ) # muuttaa pi:n kun se on rivin lopussa #[[ $(echo "$tulos" | grep -o pi[^a-z0-9] ) ]] &&
tulos=$(echo $tulos | sed "s/pi\^/$pi_numeroina\^/g;s/pi\*/$pi_numeroina\*/g;s/pi\-/$pi_numeroina\-/g;s/pi\//$pi_numeroina\//g;s/pi[+]/$pi_numeroina\+/g" )

# ratkaistaan kaikki tieteelliset esitysmuodot (niinkuin: 1.23e17)
apu=$(echo $tulos | grep -o [0-9]e.[0-9]* )
while [[  $apu != "" ]] ; do muuta_e_esitys_numeroiksi; apu=$(echo $tulos | grep -o [0-9]e.[0-9]* ); done

tput cuu1; tput el # kursori ylös rivinverran ja rivin tyhjennys
echo #"$tulos"

#korkeintaso=0; [[ ${tulos#*\[} ]] &&
etsi_laskukaavan_korkeimman_tason_vasemmanpuoleisimman_sulun_teksti

[[ $korkeintaso -gt 0 ]] && laita_se_laskentaan_ja_korvaa_sulun_teksti_lasketulla_arvolla #&& return

for funktiolaji in asin sin cos atan tan log ln exp sqrt int abs kymppiin kahteen annuiteetti ! ; do
korvauksia_tekematta=1
while [ $korvauksia_tekematta -eq 1 ];                                                                                    do
korvauksia_tekematta=0
[[ $(echo $tulos | grep $funktiolaji ) ]] && korvauksia_tekematta=1 && erota_parametrit_ja_kutsu_funktiota $funktiolaji ; done
                                                                                                  done
# ratkaise x^y kaikkialla, sillä bc ei yksinään ymmärrä desimaalisia eksponentteja
apu=$(echo $tulos | grep -o [0-9.][0-9.]*^[0-9.+-][0-9.]* | tr "\n" " " | awk '{print $1}')

while [[  $apu != "" ]] ; do ratkaise_eksponentti $apu; apu=$(echo $tulos | grep -o [0-9.][0-9.]*^[0-9.+-][0-9.]* | tr "\n" " " | awk '{print $1}'); done
tulos=$(echo $tulos | sed 's/--/+/g') && tulos=$(echo "obase=10;ibase=10;scale=$desimaaleja ; $tulos" | bc -l | tr -d '\\' | tr -d "\n" ) && tulosta $tulos
}

function erota_parametrit_ja_kutsu_funktiota () {
[[ $funktiolaji = ! ]] && apu=$(echo ${tulos%%\!*}  | sed 's/\^/ /g;s/\*/ /g;s/\// /g;s/\+/ /g;s/\-/ /g') && numero=${apu##* }
[[ $funktiolaji != ! ]] && apu=$(echo ${tulos#*$funktiolaji} | sed  's/\^/ /g;s/\*/ /g;s/\// /g;s/\+/ /g;s/\-/ /g') && numero=${apu%% *}
[[ $numero = "" ]] && apuu=$(echo ${tulos#*$funktiolaji}) && apu=${apuu:0:1}${apu:1} && numero=${apu%% *} # palautetaan operaattoreita poistettaessa hävinnyt merkki
kutsu="$funktiolaji $numero"; $kutsu; arvo=$($kutsu); korvattava=$funktiolaji$numero;[[ $funktiolaji = ! ]] && korvattava=$numero$funktiolaji;tulos=$(echo $tulos | sed "s/$korvattava/$arvo/g")
}

function tulosta () { #  mikäli luvussa on desimaalipiste niin poistetaan peränollat ja pistekin jos se jää loppuun yksikseen
[[ ${1%%\.*} != $1 ]] && echo $1 | sed 's/0*$//g' | sed 's/\.$//g' || echo $1
}
 
function ratkaise_eksponentti () { # ratkaistaan: x^y sillä ilman apua bc ei ymmärrä desimaalisia eksponentteja
[[ $(echo $tulos | grep '\^' ) = "" ]] && return
lukuedessa=${tulos%%^*}
etukaannettyna=$(echo $lukuedessa | rev)  
kantaluku=$(echo ${etukaannettyna%%[!\.0-9]*} | rev)  
exponentti=$(echo ${tulos##*\^} | sed 's/\^/ /g;s/\*/ /g;s/\// /g;s/\+/ /g;s/[0-9]\-/ /g') # 420
valitulos=$(echo "scale=$desimaaleja; e($exponentti*l($kantaluku))" | bc -l | tr -d '\\' | tr -d "\n")
korvattava=$kantaluku"\^"$exponentti; tulos=$(echo $tulos | sed "s/$korvattava/$valitulos/g")
echo $kantaluku'^'$exponentti' '$valitulos
}
 
function etsi_laskukaavan_korkeimman_tason_vasemmanpuoleisimman_sulun_teksti  () { # echo "etsitään tasoa"
raja=112\101\116\116\101\114\105\73\73\73
korkeintaso=0; olintaso=0
for (( n=0; n<=${#tulos}; n++ )); do
  [[ ${tulos:$n:1} = "[" ]] && let olintaso++  
  [[ $olintaso -gt $korkeintaso ]] && korkeintaso=$olintaso && tekstinalku=$n
  [[ ${tulos:$n:1} = "]" ]] && let olintaso--
done
[[ $korkeintaso -eq 0 ]] && return
for (( m=tekstinalku; m<=${#tulos}; m++ )); do
  [[ ${tulos:$m:1} = "]" ]]  &&  tekstinloppu=$m && break
done
}

function laita_se_laskentaan_ja_korvaa_sulun_teksti_lasketulla_arvolla () {
tulos_alussa="$tulos"
suluissa_oleva="${tulos:$tekstinalku:$(($tekstinloppu-$tekstinalku))}" # oli: -$tekstinalku+1))}"
ilman_sulkuja=$(echo $suluissa_oleva | sed 's/^\[*//g;s/\]*$//g');  
laske $ilman_sulkuja
uusi_tulos=${tulos_alussa:0:$tekstinalku}$tulos${tulos_alussa:$tekstinloppu+1}; tulos=$uusi_tulos; echo $tulos
etsi_laskukaavan_korkeimman_tason_vasemmanpuoleisimman_sulun_teksti $tulos  
[[ $korkeintaso -gt 0 ]] && laita_se_laskentaan_ja_korvaa_sulun_teksti_lasketulla_arvolla  # koe [[ $korkeintaso -gt 0 ]] && laske $tulos
}

function muuta_e_esitys_numeroiksi  () { # ratkaistaan tieteellinen esitystapa; luvut mallia 1.23e18                                              
korvattava=$(echo $tulos | grep -o [.0-9]*e[-+0-9][0-9]* )
[[ $korvattava = "" ]] && return
arvo=$(echo $korvattava | sed "s/e/\*10\^/g")
tulos=$(echo $tulos | sed "s/$korvattava/"\["$arvo"\]"/g")
}

function maaraa_laskujen_desimaaliluku () {
desimaaleja=$(echo ${tulos##*des} | sed 's/[[:alpha:]]//g')
korvattava="des"$desimaaleja; tulos=$(echo $tulos | sed "s/$korvattava//g")
}

function tan () {
asteluku=$(echo ${1#+}) # jos asteluvun edessä on + niin  poistetaan se
[[ $lasketaan_radiaaneissa -eq 1 ]] && tan=$(echo "scale=$desimaaleja; s($asteluku)/c($asteluku)" | bc -l | tr -d '\\' | tr -d "\n") || tan=$(echo "scale=$desimaaleja; s($asteluku*$pi_numeroina/180)/c($asteluku*$pi_numeroina/180)" | bc -l | tr -d '\\' | tr -d "\n")  ; tulosta $tan
}

function kahteen () {
kahteen=$(echo "obase=2;ibase=10;$1" | bc -l | tr -d '\\' | tr -d "\n" ) ; tulosta $kahteen
}

function kymppiin () {
kymppiin=$(echo "obase=10;ibase=2;$1" | bc -l | tr -d '\\' | tr -d "\n" ) ; tulosta $kymppiin
}

function cos () {
asteluku=$(echo ${1#+}) # jos asteluvun edessä on + niin  poistetaan se
[[ $lasketaan_radiaaneissa -eq 1 ]] && cos=$(echo "scale=$desimaaleja; c($asteluku)" | bc -l | tr -d '\\' | tr -d "\n") || cos=$(echo "scale=$desimaaleja; c($asteluku*$pi_numeroina/180)" | bc -l | tr -d '\\' | tr -d "\n") ; tulosta $cos
}

function log () { # briggsin logaritmi
log=$(echo "scale=$desimaaleja; l("$(echo $1 | sed "s/e/$e_numeroina/g")")/l(10)" | bc -l | tr -d '\\' | tr -d "\n"); tulosta $log
}

function ln () { # e-kantainen logaritmi
ln=$(echo "scale=$desimaaleja; l($1)" | bc -l | tr -d '\\' | tr -d "\n"); tulosta $ln  
}

function exp ()  { # e^x
exp=$(echo "scale=$desimaaleja; e($1)" | bc -l | tr -d '\\' | tr -d "\n"); tulosta $exp
}

function sqrt () { # neliöjuuri
sqrt=$(echo "scale=$desimaaleja; sqrt ($1)" | bc -l | tr -d '\\' | tr -d "\n"); tulosta $sqrt
}

function ! () {
[[ $1 -eq 0 ]] && kertoma=1 || kertoma=$( eval echo {1..$1} | tr " " \* | bc | tr -d '\\' | tr -d "\n"); tulosta $kertoma
}

function atan () { # arctangentti
[[ $lasketaan_radiaaneissa -eq 1 ]] && atan=$(echo "scale=$desimaaleja; a($1)" | bc -l | tr -d '\\' | tr -d "\n") || atan=$(echo "scale=$desimaaleja; a($1*$pi_numeroina/180)" | bc -l | tr -d '\\' | tr -d "\n") ; tulosta $atan
}

function sin () {
asteluku=$(echo ${1#+}) # jos asteluvun edessä on + niin  poistetaan se
[[ $lasketaan_radiaaneissa -eq 1 ]] && sin=$(echo "scale=$desimaaleja; s($asteluku)" | bc -l | tr -d '\\' | tr -d "\n") || sin=$(echo "scale=$desimaaleja; s($asteluku*$pi_numeroina/180)" | bc -l | tr -d '\\' | tr -d "\n") ; tulosta $sin
}

function asin () { # arcsini
[[ $lasketaan_radiaaneissa -eq 1 ]] && asin=$(echo "scale=${desimaaleja:-66}; a($1/sqrt(1-($1*$1)))" | bc -l | tr -d '\\' | tr -d "\n") || asin=$(echo "scale=${desimaaleja:-66}; a($1/sqrt(1-($1*$1)))*180/$pi_numeroina" | bc -l | tr -d '\\' | tr -d "\n")  
tulos=$(echo $tulos | sed "s/asin$1/$asin/g");tulosta $asin
}

function abs () { # tämä poistaa etumerkin, myös plussan
abs=$1; abs=$(echo ${abs#[-+]}); tulosta $abs
}

function int () { # muuttujan kokonaisluku-osa
int=$(echo 0$1 | cut -d. -f1 ); tulosta $int
}

function annuiteetti () {
laske [[1+$korkoprosentti/100]^$lainaaika*$korkoprosentti/100]/[[1+$korkoprosentti/100]^$lainaaika-1]*$lainamaara
annuiteetti=$tulos
}

function ratkaise_annuiteetti () { # lainanmäärä korkoprosentti lainaaika(vuosissa)
set -- $(echo $tulos | sed 's/annuiteetti//g')
lainamaara=$1
korkoprosentti=$2
lainaaika=$3
echo 'annuiteetti '$lainamaara' '$korkoprosentti' '$lainaaika
annuiteetti #kutsu="annuiteetti";arvo=$("$kutsu"); korvattava="annuiteetti $lainamaara $korkoprosentti $lainaaika"; tulos=$(echo $tulos | sed "s/$korvattava/$arvo/g"); echo $annuiteetti
}
« Viimeksi muokattu: 02.07.14 - klo:19.12 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #70 : 18.07.11 - klo:06.14 »
BASH-skripteissä ei pitäisi olla tällaista 'normaaliohjelmointia' ja jos sitä on pakko käyttää on se yleensä merkki siitä ettei skriptiä ole tehty parhaalla mahdollisella tavalla. Silti tällaiset rakenteet täytyy löytyä sillä eihän parasta tapaa kannata edes etsiä jos toiminta on muutenkin kelvollista.

Pinon käsittely:
- pinoon lisätään käskyllä:           pinoa pinottavan_muuttujan_nimi          
- pinon päältä luetaan käskyllä:   ensiksi_pinottu pinottavan_muuttujan_nimi
- pinon alta luetaan käskyllä:     viimeksi_pinottu pinottavan_muuttujan_nimi

- luettaessa pinosta silloinkin kun se on tyhjä ei aiheuta virhettä, luettu jää vain tyhjäksi ja sen perusteella toimiminen jää kutsujan tehtäväksi
- toimii sekä numeroille että tekstille (vain sanoille, ei lauseille).
- ainoastaaan pinon päälle voi lisätä mutta lukea voidaan kummastakin päästä vaikka samassa skriptissä vuorotellen.
- koodia lisäämällä saa muuttujat local-tyyppisiksi. Mutta koodista tulisi suurempi ja toimintanopeuskin laskisi.
- jos valittavien joukossa on välilyönti se jätetään valittavien joukosta pois. Virhe se kuitenkaan ei ole.
- Linuxissa on bc:n lisäksi toinenkin kalkulaattori. Nimeltään se on dc. Se on vaikeakäyttöinen ja pino-perusteinen. Sen taitajat vannovat sen nimeen. Pitääpä palauttaa mieleen kuinka sitä käytetään.

Koodia: [Valitse]
#!/bin/bash

function pinoa () {
[[ ! $pinoosoitin ]] && pinoosoitin=0 && pinonpohja=0
for n in $1; do pino[$pinoosoitin]=$n; let pinoosoitin++; done
}

function viimeksi_pinottu () {
[[ $pinoosoitin>0 ]] && let pinoosoitin--
eval $1=${pino[$pinoosoitin]}
unset pino[$pinoosoitin]
}

function ensiksi_pinottu () {
eval $1=${pino[$pinonpohja]}
unset pino[$pinonpohja]
let pinonpohja++
}

# pääohjelma: pelkkää kokeilua
pinoa 0
pinoa "1 2 3 4 5 6 7 8 9 10 11 12"
pinoa "yksi 2 kolme ja vieläkin yksi"
while true; do
  ensiksi_pinottu apu  #  kutsuttaessa: viimeksi_pinottu tulostus-järjestys muuttuu  
  [[ !  $apu ]] && break
  echo $apu
  read
done
[[ ${pino[*]} ]] && echo 'tässä ei pitäisi tulostaa mitään sillä pinon pitäisi olla tässävaiheessa tyhjä'
read -p 'paina enter jatkaakseesi'
« Viimeksi muokattu: 19.04.12 - klo:19.55 kirjoittanut petteriIII »

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #71 : 19.07.11 - klo:20.49 »
Taas kertaalleen tuntuu siltä ettei rajaa skriptien nopeuttamiseksi olekaan. Samaan hölmöyteen kompastuu joka kerta: ainakin minä yritän ratkaista ongelmat itse enkä tajua käyttää käyttöjärjestelmän rutiineja.
- muuten jo tehdyn skriptin muuttaminen käyttöjärjestelmää paremmin käyttäväksi on helpompaa kun tekee koko skriptin uusiksi.

Tein skriptin jonka tarkoitus oli laskea skriptikansion skriptien lukumäärä: skriptikansiossa on monia alikansioita joissa on skriptejä dokumentteineen. Skripti toimi kyllä, mutta vähän hidas se oli. Sitten muunsin skriptin käyttämään enemmän käyttöjärjestelmää. Nyt skripti on niin nopea ettei kättään kerkiä näppäimistöltä nostaa kun on jo valmis.

- Skriptin suoritusajan mittaamiseen tarkoitettu time-käsky esittää kolme arvoa tarkoituksenaan kertoa muunmuassa se kuinka nopea skripti on ja millaiset ovat mahdollisuudet nopeuttaa sitä. Arvot ovat:  Real, User ja Sys. Suhde Real/Sys kertoo kuinka paljon on nopeuttamisen varaa: mitä suurempi arvo on sitä enemmän voi nopeuttaa.

Hitaana skriptin arvot olivat:
real   0m2.096s
user   0m1.804s
sys   0m0.224
- suhde 9.4

Nopeutettuna skriptin arvot ovat:
real   0m0.176s
user   0m0.092s
sys   0m0.044s
- suhde 4. Nopeuttaminen olisi varmaan vieläkin mahdollista, mutta nopeus riittää tämänhetkisessä tilanteessa kun skriptejä on vajaa tuhat ja muita tiedostoja muutamia satoja.

Koodia: [Valitse]
#!/bin/bash
skriptienluku=0
for tiedostonimi in $(grep -lr / ~/omatskriptit | grep -v /ARKISTO/)
do
  read -N 3 tiedoston_alku < $tiedostonimi # luetaan tiedostosta 3 ensimmäistä merkkiä
  [[ $tiedoston_alku = "#!/" ]] && let skriptienluku++
done
echo "skriptienluku="$skriptienluku

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #72 : 20.07.11 - klo:09.15 »
Asian vierestä / idea: 
Joskus kun "on kiire" kannattaa tehdä asioita rinnakkain eikä peräkkäin jos se on mahdollista.  Testasin hieman tuota ideaa aiemmin kun joku halusi "nopean pingauksen".  Kirjoitin silmukan joka käynnistää rinnakkain 254 ping -komentoa, odottelee kun kaikki nuo ovat valmistuneet ja näyttää tulokset jos jotain löytyi.  Mukavaa katsella kun koneessa käynnistyy prosesseja :)  Mitenköhän monta noita voisi laittaa samaan aikaan käyntiin ?  Tuo rinnakkaisping tekee myös tehtävänsä rivakasti.
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #73 : 22.07.11 - klo:17.42 »
Asian vierestä / idea: 
Joskus kun "on kiire" kannattaa tehdä asioita rinnakkain eikä peräkkäin jos se on mahdollista. 
...

Minulle ainakin on tarve tällaiselle ja toivon että näin saisin skriptissäni toimimaan siedettävän nopeasti kun luen editoriin monta tiedostoa yhdellä kertaa tyyliin:
gedit tiedosto1 tiedosto2 tiedosto3 ... tiedosto12
- toimii kyllä myös kun määrää: (gedit tiedosto1 tiedosto2 tiedosto3 ... tiedosto12&) mutta tiedostot latautuvat yhtä hitaasti kuin ennen
- tiedostot ovat suurinpiirtein samakokoisia.
- ei se kestä kuin 4 sekuntia mutta parempi olisi kun kestäisi vajaan sekunnin.
 

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #74 : 23.07.11 - klo:22.37 »
Lainaus
- toimii kyllä myös kun määrää: (gedit tiedosto1 tiedosto2 tiedosto3 ... tiedosto12&) mutta tiedostot latautuvat yhtä hitaasti kuin ennen

Entäs näin:

gedit tiedosto1 &
gedit tiedosto2 &
gedit tiedosto3 &
.
.
.
jne.



Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #75 : 24.07.11 - klo:08.12 »
Entäs näin:

gedit tiedosto1 &
gedit tiedosto2 &
gedit tiedosto3 &
.
.
jne.

Tattista, auttoihan se. Gedit itse on vielä hidas mutta parempi gedit on kuulemma tulossa.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #76 : 24.07.11 - klo:11.53 »
Tietääkö onko jotain tapaa tehostaa .sh-skriptien toimintaa tai jopa konvertoida tai kääntää niitä johonkin tehokkaampaan muotoon?

Nyt vasta törmäsin yhteen opastukseen, joten taitaa olla myöhässä tähän asiaan. Lisäksi luulen että koodin nopeus ei juurikaan nouse (sattan olla väärässä joten kokeilla kannattaa) vaan tarkoitus on lähinnä estää koodin muokkaaminen, tai salata koodi.

http://alnazmin.blogspot.com/2011/07/how-to-compile-bash-script-using-shc.html

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #77 : 06.08.11 - klo:06.00 »
BASH:in käsky: eval on osoittautunut tärkeäksi. Se kertoo BASH:ille että yksi kierros lisää tulkkausta olisi tarpeen. Toinen 'sinnepäin peukalosääntö': se muuttaa tekstijonon käskyksi. Sitä tarvitaan esimerkiksi:
- funktiossa nimiparametri jää ilman eval-käskyä siksi miksi sitä nimitetäänkin: nimeksi. Eval muuttaa sen arvoksi.
- joidenkin rakenteiden sisällä olevaa ei laajenneta ellei käskyllä eval kerrota BASH:ille että nyt laajennetaan.
- yksi mielenkiintoinen käyttö esitetään sivulla: http://www.linuxjournal.com/content/bash-preserving-whitespace-using-set-and-eval
- joskus samassa ilmauksessa on osia jotka täytyy laajentaa ja osia joita ei saa laajentaa. Ratkaisu on että eval määrätään ihan normaalisti, mutta ne osat joita ei saa laajentaa suojellaan laittamalla se kovien lainausmerkkien väliin. Yleensä kovat lainausmerkit lisätään yhdistelmällä: \'     . Siis keno, ei /


Eval-käsky on kuulemma vaarallinen. Käyttöjärjestelmän omissa skripteissä sitä kuitenkin esiintyy paljonkin niinkuin muuten myös goto-käskyä. Mutta aivan kuten aikoinaan goto-käskyn kanssa kunniallista syytä vaarallisuuteen ei esitetä, puhutaan vain epämääräisesti tietoturvasta. On ihan mahdollista että kunnollinen syy on olemassa ja ettei sitä voi käsittää muut kuin teoreettisen ohjelmoinnin tuntijat. Mutta ihan mahdollista on sekin, että niin väitetään jottei oma tietämättömyys paljastuisi. Tottakai siinä on vähän tottakin, sillä ainoa turvallinen PC on se joka on sammuksissa, rikki ja merenpohjalla.

- naurasko vaiko itkis: jos joku ei toimi mitenkään muuten niin laita sen eteen eval.
« Viimeksi muokattu: 24.08.11 - klo:05.50 kirjoittanut petteriIII »

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #78 : 06.08.11 - klo:10.59 »
Lainaus
Mutta aivan kuten aikoinaan goto-käskyn kanssa kunniallista syytä vaarallisuuteen ei esitetä, puhutaan vain epämääräisesti tietoturvasta.
Olettaisin tai ainakaan minulla ei ole parempaa tietoa tuosta "goto" -käskystä kuin että runsaasti viljeltynä se tekee koodista "spagettia", rikkoo koodin lohkorakennetta, toiminnan/rakenteen seuraaminen isommassa ohjelmassa vaatii pyörittelyä ja etsimistä sieltä täältä.  En keksi syytä miksi siitä olisi jotain teknistä "vaaraa", sitä vaan pidetään huonona rakenteellisena toteutuksena.   Ensimmäisellä kerralla voi olla helppoa kutoa tuo spagetti mutta kun vuoden päästä siihen tarvitaan jokin pieni muutos voi olla jo hankalampaa. 
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #79 : 06.08.11 - klo:12.33 »
...
 Ensimmäisellä kerralla voi olla helppoa kutoa tuo spagetti mutta kun vuoden päästä siihen tarvitaan jokin pieni muutos voi olla jo hankalampaa.  

En kiistä; kyllähän goto houkuttelee tekemään spagettia ja BASH+goto houkuttelisi vielä enemmän. Mutta sen kiistän että niin goto kuin mikään muukaan käsky olisi aina paha.  

Goto+label toimii varmaan BASHissa vieläkin koska grep löytää niitä binäärisistä skripteistä joista ei saa ohjelmalistausta että näkisi varmasti, ja kokeilla en halua sillä en kuvittelisikaan käyttäväni niitä sillä niistä oli niin hirveä huuto aikanaan oli että sieluuni jäi vamma.
« Viimeksi muokattu: 06.08.11 - klo:14.27 kirjoittanut petteriIII »