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

kamara

  • Käyttäjä
  • Viestejä: 3031
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #160 : 08.08.14 - klo:13.21 »
Kysymys:
Miten shell-scriptillä saisi välitettyä useamman argumentin komentorivi-ohjelmalle vaiheittain ja sitten suljettua ohjelman?
Esim. echo 1+2 | octave
käynnistää octave:n, palauttaa tuloksen ans = 3 ja sulkee automaattisesti octave:n.

Entä jos haluaisin octave:n laskevan kaksi operaatiota ja sulkeutuvan vasta sitten? Esim. 1+2 ja 2+3 ja sulkeutuvan vasta toisen operaation jälkeen. Esimerkkien lopputulokset tulostuisivat shell:iin "ans = 3" ja "ans = 5".

Haetko jotain tällaista?
Koodia: [Valitse]
echo $1+$2|octave
eli tee nanolla oct.sh, ja anna sille suoritusoikeudet ja aja ohjelma päätteessä:
Koodia: [Valitse]
chmod 755 oct.sh
./oct.sh

Parametrien määrän saa seuraavasti:
Koodia: [Valitse]
echo ${#@}
« Viimeksi muokattu: 08.08.14 - klo:13.37 kirjoittanut kamara »

kamara

  • Käyttäjä
  • Viestejä: 3031
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #161 : 08.08.14 - klo:13.43 »
Vai ajatkohan tätä takaa?
Koodia: [Valitse]
echo "2+3,1+2"|octave

parametreina:
Koodia: [Valitse]
echo "$1+$2,$3+$4"|octave

rationaalinen

  • Käyttäjä
  • Viestejä: 67
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #162 : 09.08.14 - klo:21.21 »
Tervehdys!

Kamara, kiitos nopeasta ja käypäisestä vastauksesta. Testailin antamista shell:stä useammalle ohjelmalle ja esim. octavea yksinkertaisempi genius-komentorivi ohjelma ei tunnu hyväksyvän useampaa argumenttia lainausmerkkien "" sisällä pilkulla erotettuna. Komentokehoitteessa testaten:
echo "2+3,1+2" | genius
line 1: ERROR: syntax error before ','

echo "2+3" | genius
5

Mitenköhän ylemmässä tapauksessa saisi useamman argumentin menemään sisälle ohjelmaan (esimerkissä geniukseen). Lisäksi kaikki ohjelmat eivät sulkeudu automaattisesti vaan niille pitäisi saada välitettyä lopetusargumentti "quit".

t. Rationaalinen

kamara

  • Käyttäjä
  • Viestejä: 3031
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #163 : 09.08.14 - klo:21.53 »
Taitaa eri ohjelmissa olevan eri käytännöt. geniuksessa näyttää olevan print-käsky, jolla voi tulostaa useampia argumentteja:
Koodia: [Valitse]
echo "print(2+3);print(4+5)"|genius

Edit - edellisestä viestistä kuulin ensimmäisen kerran genius-ohjelmasta, joten en todellakaan ole mestari sen kanssa, mutta osasin manuaalia tavata vähän.

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #164 : 10.08.14 - klo:11.46 »
Skripti palauttaa kutsuvalle ohjelmalle yhden paluuarvon ( = exit code, return code) mutta esimerkiksi tiedoston kautta voi välittää takaisin mielivaltaisen kokoisia rakenteita.
Autamme ilolla ja ilmaiseksi omalla ajallamme.  Ethän vaadi, uhoa tai isottele näin saamasi palvelun johdosta.

rationaalinen

  • Käyttäjä
  • Viestejä: 67
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #165 : 10.08.14 - klo:14.57 »
Ciao!

Kiitoksia hyvistä neuvoista taasen kamara ja ajaaskel.

Milläköhän loitsulla debugfs nimiselle ohjelmalle saa syötettyä argumentteja? Debugfs:n manpage www:ssä:
http://linux.die.net/man/8/debugfs

tai shell:stä man debugfs.

Kaikenlaisia optioita löytyy mutten otsallani löydä kelpoista argumenttien putkittamistapaa.

echo "print(arg1);print(arg2)" | debugfs -optiot
ja
echo "arg1,arg2" | debugfs -optiot

eivät tunnu kelpaavan.

Ei ole ihan helppo laji harrastajalle;-).

kamara

  • Käyttäjä
  • Viestejä: 3031
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #166 : 10.08.14 - klo:15.18 »
Olisikohan jotain seuraavaa...
Yksi komento...
Koodia: [Valitse]
debugfs -R Komento

tai useampi komento filen avulla:
Koodia: [Valitse]
debugfs -f Komentofile

Rohkea voisi kokeilla myös seuraavaa...
Koodia: [Valitse]
echo "montakomentoa" | debugfs -f /dev/stdin

Mutta en takaa toimivuutta, enkä tiedä jääkö kyseinen käsky päälle.

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #167 : 10.08.14 - klo:23.16 »
En arvaa onko ongelmasi tämä mutta...
Noin yleisesti, syötettä voi mennä kahta täysin eri tietä:  komentoriviparametrit (command line parameters) ja vakiosyöte (standard input). Kaikki ohjelmat eivät tue molempia tai joskus pitää erikseen ilmaista jos halutaan käyttää vakiosyötettä eikä komentoriviparametreja.  Tuo putkitus käyttää vakiosyötettä.  Esimerkki "echo": n avulla joka ei lue vakiosyötettä:

Koodia: [Valitse]
echo "kissa" | echo
ei tulosta mitään (tai oikeastaan pelkän rivin siirron).

Jotta saisimme putken kautta tulevan tavaran tuonne echon perään hännille tarvitsemme jonkin apukeinon siirtää putkesta tuleva syöte "echo" komennon perään komentoriviparametreiksi.  "xargs" komento tekee tuon asian:

Koodia: [Valitse]
echo "kissa" | xargs echokissa

On myös toinenkin tapa käyttämällä "read" komentoa:

Koodia: [Valitse]
echo "kissa" | (read aaa; echo $aaa)
Aina ei ole viisasta putkittaa vaan käyttää komennon korvausta (command replacement) "$()":

Koodia: [Valitse]
echo $(echo "kissa")

Tuo sama on kerrottu esimerkiksi täällä:

http://superuser.com/questions/189362/how-to-pipe-command-output-to-other-commands
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 #168 : 13.09.14 - klo:14.16 »
Suhtaudun sed:iin, awk:iin, grep:iin ... nyt hieman toisin kuin aikaisemmin. Netistä luin että skriptiä optimoidessa on järkevää pyrkiä noista ulkoisista ohjelmista eroon. Matematiikka-skriptissä korvasinkin niistä ne joihin osasin koodata vastaavan toiminnan BASH:in alkeis-funktioilla - ja tosiaan joskus sedit-sun-muut hidastavat..

Netissähän nyt puhutaan mitä vaan. Ja taidottoman skriptaajan havainnot merkitsee aika olemattomasti ohjelmointi-virtuoosien vuosi-kymmenien työn rinnalla. Mutta kun lisäksi ottaa huomioon että syy skriptin kääntämiseen on yleensä se ettei ulkopuoliset saa katsottua kuinka kyvytöntä koodia on tehty niin enää en usko sokeasti noihin ulkoisiin ohjelmiin.
**
Jokaisen matriisin jokaisella jäsenellä on sekä arvo että osoite. Koska on totuttu siihen että osoitteet alkavat aina nollasta ja ovat perättäisiä niin osoitteen käsittely unohdetaan. Eikä siitä tuollaisella yksinkertaisella matriisilla tulekaan harmia.

BASH:issa on vain yksiulotteinen matriisi mutta toisin kuin yleensä niin BASH:issa matriisien osoitteiksi kelpaavat kaikki positiiviset kokonaisluvut: ne voivat alkaa mistä luvusta vaan eikä niiden tarvitse olla perättäisiä. Ja arvoiksi kelpaavat kaikki luvut ja tekstijonot joissa voi olla useimpia erikoismerkkejäkin mutta ei välilyöntejä. BASH:in matriisin erikoisominaisuudet ovat matematiikassa joskus tarpeellisia ja on harmi mikäli nuo erikoisominaisuudet hukataan käsittely-rutiinien takia.

Funktioit hyväksyvät matriiseille minkä nimen hyvänsä eikä niissä tarvitse määritellä matriisin kokoa. Koko voi olla määritelty pää-ohjelmassa tai ei.

Muihinkin matriisi-operaatioihin on helppo luoda nopeat funktiot - niinkuin esimerkiksi käänteis-matriisiin, determinanttiin, rivi- ja sarakesummiin ...

Tämäntapaisten funktioiden tekemisessä joku skriptiajurin kaltainen on ehdoton edellytys, sillä kokeillessa täytyi skriptistä tehdä satoja versioita ja aikaa kuluu skriptiajurin kanssa kymmeniä tunteja mutta ilman skriptiajuria kuluisi niin monta viikkoa että eihän sitä kukaan jaksaisi.
 
Koodia: [Valitse]
#!/bin/bash

function tulosta_matriisi_näytölle () {
(echo -n "Matriisin $1 jäsenten arvot     : "; eval echo -e \${$1[@]}
echo -n "Matriisin $1 jäsenten osoitteet : "; eval echo \${!$1[*]}) | column -t
echo
}

function kirjoita_matriisi_levylle () {
eval echo  \${$1[@]} > ~/tiedosto1   # Matriisin $1 jäsenten arvot   
eval echo \${!$1[*]} > ~/tiedosto2   # Matriisin $1 jäsenten osoitteet
}

function lue_matriisi_levyltä () {
apu0=0
apu1=($(cat  ~/tiedosto1))
apu2=($(cat  ~/tiedosto2))
while true; do
  [[ -z ${apu1[$apu0]} ]] && break 
  eval "$1[${apu2[$apu0]}]"="${apu1[$apu0]}" # mielenkiintoinen lause
  let apu0++
done
unset apu0 apu1 apu2 
}

# seuraavat lauseet ovat vain sen tarkistamista että kaikki tapahtuu oikein.
matriisi1[7]=55.5
matriisi1[123]=joo
matriisi1[334455]=-777
matriisi1[1]=15e23 # matriisin jäsenet voi määritellä missä järjestyklsessä haluaa. Tulostu tapahtuu kuitenkin osoitteiden suuruusjärjestyksessä.
echo matriisi1 ennen tallettamista levylle :
tulosta_matriisi_näytölle matriisi1
kirjoita_matriisi_levylle matriisi1
unset matriisi1
lue_matriisi_levyltä matriisi1
echo matriisi1 levytä lukemisen jälkeen:
tulosta_matriisi_näytölle matriisi1
unset matriisi1
echo

matriisi2=({a..z})
echo matriisi2 ennen tallettamista levylle :
tulosta_matriisi_näytölle matriisi2
kirjoita_matriisi_levylle matriisi2
unset matriisi2
lue_matriisi_levyltä matriisi2
echo matriisi2 levyltä lukemisen jälkeen:
tulosta_matriisi_näytölle matriisi2

**
Tulipa taas uutta tietoa ja asiasta josta saa erittäin huonosti ohjeita. Homma on seuraava: käskyn tuloste siirtyy matriisiin käskyllä: matrix=($(käsky)). Mutta menetelmä ei toimi oikein mikäli tulosteessa on välilyöntejä.  Käsky muuttuu silloin hieman:
Koodia: [Valitse]

IFS=$'\n' matrix=($(käsky)); unset IFS . (unset IFS ihan vain varmuuden takia sillä teoriassahan sitä ei tarvita).

**
Yksikään virtuoosi ei dokumentoi tekemisiään kunnolla ellei ole pakko sillä ymmärrettävän dokumentin tekemisessä on paljon suurempi työ kuin koodaamisessa eikä ymmärrettävästä dokumentista ole virtuoosille itselleen hyötyä vaan hyvin ylimalkainen dokumentti on riittävä; lisäksi virtuoosit ovat neroja dokumenttien hukkaamisessa. Tunnustettuja BASH-virtuooseja oli BASH:in alkuaikoina tuhansia ja heidän työnsä päätyi dokumentoimattomana viralliseen koodiin  sillä pakkoa dokumentointiin ei juurikaan ollut. Voi olla montaakin mieltä siitä onko järkevää käyttää dokumentoimattomia ominaisuuksia, mutta sen osaan kertoa että BASH:issa on ziljoonia dokumentoimattomia ominaisuuksia.   
**
Mistähän on oikeastaan lähtöisin käsitys ettei BASH kelpaa mihinkään? Vaikka toisaalta sitähän käytetään vain linux-kielisten käyttöjärjestelmien toiminnan aloittamisessa - siis ollenkaan tärkeää?
**
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 "tässä voi olla minkähyvänsä käsky tai funktio"
**
Taas kertaalleen yritin tutustua BASH:in rinnakkaisprosessointiin mutta kokonaiskuvan saamista haittaa se, että rinnakkaisprosessointiin on 27615 ratkaisua joista useimmat osittaisia ja ohjeissa löytyy pääasiassa sutta&sekundaa:
1. Itse linux voi ajaa yhtaikaisesti monia prosesseja ja BASH hallitsee sitä käskyillään bg ja fg. Myös käskyn tai funktiokutsun perään voi lisätä: & joka siirtää suorituksen tausta-ajoksi. Käsky wait taas odottaa kunnes kaikki on tehty ja: wait $! odottaa viimeksi määrätyn prosessin loppumista ja wait $pid sen prosessin loppumista jonka pid annetaan.
2. Rinnakkaisprosessointiin on myös ohjelma nimeltään: parallel. Yksinkertainen esimerkki: time parallel sh -c ::: "sleep 1; echo 1loppu" "sleep 1; echo 2loppu" "sleep 1; echo 3loppu" joka tulostaa mitä pitäisikin ja vie aikaa 1.212 sekuntia niinkuin odottaa sopiikin.
3. Myos käskyä xargs voi käyttää

- käskynsuorituksen aikana tarvitaan usein näyttöä missä vaiheessa käskyn suoritus on eikä useimmissa käskyissä ole suoritusajan näyttöä. Siispä on useita menetelmiä lisätä tämä ominaisuus esimerkiksi rinnakkaisprosessilla. Tällaisia ohjelmia on muunmuassa: bar, pv (pipe viewer), dialog ...
« Viimeksi muokattu: 08.02.15 - klo:06.04 kirjoittanut petteriIII »

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #169 : 24.11.14 - klo:22.30 »
Lainaus
...josta mitkään ohjeet, man-sivut tai netissä olevat organisaatoiden super-virtuoosit eivät puhu...

Tuli mieleen joitakin asioita tuosta edellä olevasta.  Pieni johdanto niin tästä on iloa ehkä muillekin... 

Muuttuja joka on taulukko (engl. array)

Jossain aiemmin kerroin että Bashin muuttujat ovat luonnostaan yksiulotteisia taulukoita --- jos käytät niitä sillä tavalla.  Se mikä joissain muissa ohjelmointikielissä tunnetaan muuttujan tyyppinä määräytyy Bashissä hyvin yksinkertaisesti ilman mitään määritystä: Alat käyttää muuttujaa kuin se olisi taulukko ja se on sellainen.   Mitä tuo sitten oikeastaan tarkoittaa ?  Mainitsit tuolla sijoituslauseen joka on muotoa:

Koodia: [Valitse]
taulukko=( ...jotain...)
Tuossa  =()    -muoto kertoo Bashille että muuttujaan jolle keksin nimen "taulukko" halutaan tiputtaa sisään jotain monikenttäistä ja Bash alkaa tehdä "numeroituja laatikoita" peräkkäin alkaen numero nollasta eteenpäin eli itseasiassa meillä on sen jälkeen:

Koodia: [Valitse]
taulukko[0], taulukko[1], taulukko[2],..... taulukko[n]
eli indeksinumeroita on niin pitkälle kuin yksittäisiä asioita tuli tuolta sulkujen sisältä.

Jos haluat kurkistaa laatikkoon tai käyttää sitä johonkin niin et voi kirjoittaa pelkästään
Koodia: [Valitse]
$taulukko[0] vaan aaltosulkujen kanssa
Koodia: [Valitse]
${taulukko[0]}. Ja ne kaikki kentät yhdellä kertaa saa ilmauksella
Koodia: [Valitse]
${taulukko[@]} sijoitettua eteenpäin, tulostettua tai mitä sitten halutaankin tehdä.

Ajatellaan pientä esimerkkiä tästä  =()  -asiasta:   

Koodia: [Valitse]
teksti="kissa koira hevonen"
Tuossa meillä näyttäisi olevan kolme merkkijonoa joiden välissä on välilyönti.  Tuossa muodossa tuo koko hoito on tuolla $teksti muuttujassa kuitenkin yhdessä ainoassa "laatikossa" eli jos ajatellaan sitä taulukkona niin indeksissä nolla.   Eli jos tulostat sen niin

Koodia: [Valitse]
echo ${teksti[0]}
kissa koira hevonen

Oikeasti kyseessä onkin yksi merkkijono johon sisältyvät nuo välilyönnit eli tuo kaikki on yhtä kokonaisuutta.

Koodia: [Valitse]
taulukko=($teksti)
Tuo tiputtaa kunkin välilyönnillä erotellun sanan omaan säilöönsä (sen sijaan että ne olisivat kaikki yhdessä):

Koodia: [Valitse]
echo ${taulukko[0]}
kissa
Koodia: [Valitse]
echo ${taulukko[1]}
koira
Koodia: [Valitse]
echo ${taulukko[2]}
hevonen

Mutta:  Millä perusteella Bash pätkii sen juuri välilyönnin kohdalta ?  Vastaus on tuo "IFS" joka on yksi Bashin ennaltamääritetty muuttuja.   Oletuksena se sisältää välilyönnin eli "SPACE 20h", Tab-merkin eli "TAB 09h" ja rivinsiirron "LF  0ah".   Kurkataanpa vielä "hexdump -ohjelmalla":

Koodia: [Valitse]
hexdump -C <<< "$IFS"
00000000  20 09 0a 0a                                       | ...|
00000004

Näyttäisi olevan.

Nyt herää kysymys jos haluaisinkin pätkiä jostain muusta kohdasta kuin välilyönnin tai tabin kohdalta.  Tuo onnistuu kyllä yksinkertaisesti muuttamalla tuon IFS muuttujan arvon mutta:   Hyvä tapa on tallettaa sen sisältö ennen kuin muuttelee ja palauttaa takaisin mitä se oli kun ei enää tarvita tätä muutettua asetusta.  Ei ole suositeltavaa oikaista ja antaa "unset" sille lopuksi vaan  tehdä talletus ja palautus.  Tuo on selitetty tarkemmin edistyneissä Bash-oppaissa. Tyypillinen tallennus/palautus:

Koodia: [Valitse]
oldifs="$IFS"
...tehdään_jotain...
IFS="$oldifs"

IFS muuttujan käyttöön liittyy yksi mielenkiintoinen poikkeus jolloin sitä ei tarvitse erikseen tallettaa/palauttaa:

Jos IFS asetuksen jälkeen seuraa välittömästi samalla rivillä heti perässä joko komento tai funktio.  Tällöin muutettu IFS sisältö on voimassa vain tuon komennon tai funktion ajan.   Tuota näkee usein käytettävän "read" komennon + silmukan yhteydessä:

Koodia: [Valitse]
while IFS= read -r tiedostonimi; do
echo "$tiedostonimi"
done  < tiedostonimiä_tiedostossa.txt


jolloin lukeminen ei epäonnistu jos tiedostonimessä on välilyönti tai useampikin.

Yksi hyödyllinen mutta harvemmin tunnettu ilmaisu Bashissä on 
Koodia: [Valitse]
+= eli "append" jossa alkuperäistä muuttujaa ei korvata vaan sen perään lisätään.  Tuo "plus-yhtäläisyysmerkki" sijoitus toimii sekä tekstillä että taulukoilla.  Sillä voi tehdä tekstin ketjuttamista peräkkäin mutta taulukoiden yhteydessä se on kätevä lisäämään taulukkoon uutta sisältöä. Tekstiesimerkki:

Koodia: [Valitse]
a=mäyrä
a+=koira
echo "$a"
mäyräkoira

ja taulukolla:

Koodia: [Valitse]
taulukko+=("kissa")
taulukko+=("koira")
taulukko+=("hevonen")
echo ${taulukko[@]}
kissa koira hevonen

Tuossa nuo menivät siis indekseihin 0, 1 ja 2 muuttujassa "taulukko".  Bashissä on paljon erilaisia tapoja ilmaista asioita ja ne on dokumentoitu melko hyvin mutta silti sen oikean asian löytäminen voi olla joskus vaikeaa.  Nämä taulukkoasiat (array) löytyvät täältä:

http://tldp.org/LDP/abs/html/arrays.html

Muutenkin tuo on se opas jota koodaajat käyttävät hallitsevana dokumentaationa, alkusivu on tässä:

http://tldp.org/LDP/abs/html/


Teksti-indeksin käyttö (associative array)

On yksi tilanne jossa taulukko _täytyy_ myös Bashin tapauksessa määritellä ennakolta:  Jos halutaan käyttää hieman erikoisempaa taulukkoa jossa taulukon solujen indeksit  eivät ole numeroita 0, 1, 2,...  vaan niille annetaan nimet (jotka voivat olla mitä vain haluat keksiä tilanteen mukaan).  Tällöin sekä taulukkoon tallettaminen että sinne lisäys tapahtuu noiden nimi-indeksien avulla eli voidaan ajatella mielikuvana että tavarat ovat tallessa levällään omissa nimetyissä paikoissaan missä lienevätkin mutta nimi-indeksillä löytyy indeksinumeron asemasta. Ehkä postilaatikosto jossain taloyhtiössä kuvaisi sitä hyvin:

Koodia: [Valitse]
declare -A postilaatikosto
eli määrittelimme muuttujan "postilaatikosto". Lukumäärää ei tarvitse kertoa missään Bashin taulukossa, niitä laatikoita on aina se mikä tarvitaan.

Tiputetaan jotain noihin postilaatikoihin nimi-indeksillä:

Koodia: [Valitse]
postilaatikosto[Nieminen]="myyntikirje"
postilaatikosto[Mattila]="karhukirje"
postilaatikosto[Sievänen]="rakkauskirje"
postilaatikosto[Matti Nykänen]="suksiesite"

ja tulostetaan koko laatikosto:

Koodia: [Valitse]
echo ${postilaatikosto[@]}myyntikirje karhukirje rakkauskirje suksiesite

Pieni mielenkiintoinen yksityiskohta:  Indeksi voi olla monisanainenkin tai aika mielivaltainen merkkijono, tuossa oli indeksinä "Matti Nykänen" eli skanditkin kelpaavat.  En ole tutkinut aiheuttaako välilyönti indeksin nimessä jossain yhteydessä kiusaa.

Tekisikö mieli kurkistaa mitä tapahtuu jos laittaakin numeron nyt indeksiksi ?   Mitä mahtaisi tapahtua ?   No ei oikeastaan mitään hyödyllistä sillä:   Numero 0, 1, 2... ei nyt olekaan numero --- vaan nimi.  Ei löydy mitään tuolta nimillä "0" tai "1".

Koko taulukko tyhjenee:

Koodia: [Valitse]
unset postilaatikosto
« Viimeksi muokattu: 27.11.14 - klo:09.30 kirjoittanut ajaaskel »
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 #170 : 28.12.14 - klo:20.33 »
Olen etsinyt tietoa BASH:ista aikaisemmin melkein yksinomaan googlella sillä kun aina sillointällöin olen kokeillut muita hakukoneita en ole saanut mielestäni tyydyttävän monia laadukkaita tuloksia. Mutta puolisen vuotta sitten käytin jonkunverran DuckDuckGo:ta sillä sieltä alkoi tulla tuloksia. Koska gedit höpertää nyt etsin milloin "gedit 3.10.2" tulee Ubuntuun. Muut hakukoneet antoivat tuloksia jopa paremmin kuin google. Missä mennään ?
- muuten tuloaikataulu ei selvinnyt mistään.

ajaaskel

  • Palvelimen ylläpitäjä
  • Käyttäjä
  • Viestejä: 3401
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #171 : 28.12.14 - klo:20.47 »
Itse käytän "geany" -editoria ohjelmien editointiin jos grafiikka on käytettävissä, muualla "nano" tai "vim". 
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 #172 : 29.12.14 - klo:06.34 »
Tattista taas kertaalleen. Olen harkinnut ennenkin josko siirtyisi käyttämään jotakin muuta kuin gedit:tiä, mutta olen pelännyt että siirtyminen aiheuttaisi määrättömästi työtä. Mutta osoittautuikin että toimiikin heti kun teki muutaman asetuksen - ja samalla selvisi että geanyssä on paljon sellaista mitä geditissä on kaivannut.

nm

  • Käyttäjä
  • Viestejä: 16428
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #173 : 29.12.14 - klo:12.02 »
Koska gedit höpertää nyt etsin milloin "gedit 3.10.2" tulee Ubuntuun.

Ubuntu 14.04:ssä on jo gedit 3.10.4: http://packages.ubuntu.com/trusty/gedit

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #174 : 29.12.14 - klo:16.03 »
Jokatapauksessa gedit höpertää ja geany ei. Olen ennenkin valittanut huonoa muistiani ja ilmeisesti olen etsinyt gedit3.12:sta. Jostakin luin että se tuo helpotuksen esimerkiksi siihen etteivät rivinumerot näy jja asetuksetkin alkaa taas toimia.

nm

  • Käyttäjä
  • Viestejä: 16428
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #175 : 29.12.14 - klo:17.13 »
Jostakin luin että se tuo helpotuksen esimerkiksi siihen etteivät rivinumerot näy jja asetuksetkin alkaa taas toimia.

Oletko asettanut rivinumerot näkyviin? Ainakin 14.04:ssä toimii kuten aina ennenkin, kun kytken numerot päälle: Muokkaa->Asetukset->Näytä, Näytä rivinumerot. Unityssä Muokkaa-valikko on työpöydän yläpaneelissa, jossa sijaitsevat valikot ilmaantuvat näkyviin vain, kun ohjelman ikkuna on valittuna ja viet hiiren osoittimen sinne yläpaneeliin.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #176 : 06.01.15 - klo:21.37 »
Kyllä niiden rivinumeroiden näyttäminen on asetettu ja rivinumeroille tuleekin tila muttei ne silti näy. Kansainvälisillä foorumeilla sanottiin etteivät geditin rivinumerot toimi kaikilla teemoilla ihan niinkuin niillä rivinumeroiden ja taustan värit olisivat samat. En kuitenkaan alkanut tapella geditini kanssa koska kohtahan siihen tulee korjaus ihan automaattisesti.

Mutta myös kursori ei oikein näy ja kopiointi on siten melkein mahdotonta ja tekstiä on vaikea korjata.

Ja joskus tulee kummallisia virheviestejä, mutta kehitysversiollahan sen kyllä käsittää.

**

Asiasta toiseen: olen aina ihmetellyt BASH:in huonoa statusta sillä käsittääkseeni Linux nousee pystyyn BASH-skriptien ohjaamien sovellus-ohjelmien avulla. Ja silti mitään ei tehdä vaikka noita ShellShockin kaltaisia aukkoja kuulemma on useampiakin - siis niiden 8:n? jo löytyneen ja paikatun lisäksi. Mikä ihme mättää ? Luuleeko ne että BASH on tarkoitettu ohjelmointiin ?

Tomin

  • Palvelimen ylläpitäjä
  • Käyttäjä / moderaattori+
  • Viestejä: 11481
    • Profiili
    • Tomin kotisivut
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #177 : 06.01.15 - klo:22.40 »
Asiasta toiseen: olen aina ihmetellyt BASH:in huonoa statusta sillä käsittääkseeni Linux nousee pystyyn BASH-skriptien ohjaamien sovellus-ohjelmien avulla. Ja silti mitään ei tehdä vaikka noita ShellShockin kaltaisia aukkoja kuulemma on useampiakin - siis niiden 8:n? jo löytyneen ja paikatun lisäksi. Mikä ihme mättää ? Luuleeko ne että BASH on tarkoitettu ohjelmointiin ?

Oletko kuullut systemd:stä? Sehän ei käytä bash-skriptejä, kuten perinteinen init ja on saanut siitä syystä paljon arvostelua.
Automaattinen allekirjoitus:
Lisäisitkö [RATKAISTU] ketjun ensimmäisen viestin aiheeseen ongelman ratkettua, kiitos.

petteriIII

  • Käyttäjä
  • Viestejä: 693
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #178 : 07.01.15 - klo:05.04 »
Oletko kuullut systemd:stä? Sehän ei käytä bash-skriptejä, kuten perinteinen init ja on saanut siitä syystä paljon arvostelua.

Enpä ollut kuullut, tattista kun kerroit - ja tiedänpä nyt tutkia. Siis toki olin kuullut systemd:stä mutten oletin että se olisi jokseenkin samanlainen kuin vanhatkin.  Tavallaan olen kyllä aavistellut että jotakin tämmöistä on tekeillä sillä tällätavoinhan on aina tehty; kyse ei kai ole niinkään että joku olisi parempi vaan kyse taitaa olla ohjelmoija-sukupolven vaihtamisesta. Eipä silti, kyllä systemd tuntuu ihan hyvältä näin pikaisesti arvostellen. 
- kuinka muuten systemd ja Ubuntu ? Sillä joku distro ei siirry siihen.

**

Yksi BASH:in puutteista luullaan olevan ettei se tunne funktiokutsun tarkennetta elikä kutsumuotoa: a.b  . Mutta itseasiassa BASH:issa on tuo tarkenne jo luonnostaan ja sitä käytetään seuraavasti:
Koodia: [Valitse]
#!/bin/bash
function a () {
  $@
}

function b () {
  echo toimii
}

a b   # jos välttämättä haluaa käyttää kutsussa pistettä täytyy kutsu kirjoittaa: $(echo a.b | tr . " ")

Tapa on hankala ohjelmoida, mutta muissa kielissä se on kielen ohjelmointimäärityksissä yhtä hankala - siis määrityksissä jotka ovat kirjasto-ohjelmissa eikä niitä muilla kielillä tarvitse itse määritellä. Mutta koska BASH:issa ei ole valmis-kirjastoja jää kaikille väärä käsitys ja hankala-käyttöisyys ellei tee itse kirjastoa.
- niinkuin kaikkiin muihinkin ongelmiin löytyy BASH:in käskyistä tähänkin leegio muitakin ratkaisuja.
- maailmalla on moniakin paikkoja joissa on valmiita BASH-kirjastoja. Mutta nuo maailmalta löytyvät kirjastot ovat niin nössöjä ettei niitä kannata käyttää.

Monitarkenteinen kutsu on vielä hankalampi, mutta painotan taas että kaikissa kielissä homma on yhtä hankala jos ei käytetä kirjastoa.  Monitarkenteisen funktion rungon malli on seuraava (siis ennenkuin käskyä voi käyttää täytyy jokaisella tarkennetasolla määritellä oma funktio sen kaikille mahdollisuuksille ja sijoittaa vaadittavat lisäykset oikeaan paikkaan, siis todella iso tehtävä jonka BASH:ia käyttäessään joutuu tekemään itse):
Koodia: [Valitse]
#!/bin/bash
# petteriIII 10.1.1015
function a () {
echo suoritetaan funktiota a jonka jälkeen mennään suorittamaan tarkenteen osaa ${1#.}
[[ ${1%%.*} != ${1#*.} ]] && ${1/./" "} || $1; exit # selväkielellä=>mikäli funktiossa on pisteitä niin poistetaan niistä ensimmäinen ja
                                                            kutsutaan  muodostuneella seuraavaa funktiota ja jos pistettä ei ole on kutsuna itse
                                                            parametri.
}

function b () {
echo suoritetaan funktiota b jonka jälkeen mennään suorittamaan tarkenteen osaa ${1#.}
[[ ${1%%.*} != ${1#*.} ]] && ${1/./" "} || $1; exit
}

function c () {
echo suoritetaan funktiota c, jonka jälkeen mennään suorittamaan tarkenteen osaa ${1#.}
[[ ${1%%.*} != ${1#*.} ]] && ${1/./" "} || $1; exit
}

function d () {
echo suoritetaan funktiota d, jonka jälkeen mennään suorittamaan tarkenteen osaa ${1#.}
[[ ${1%%.*} != ${1#*.} ]] && ${1/./" "} || $1; exit
}
 
a b.c.d # toki kutsu voi olla millainen hyvänsä, esimerkiksi; a d.a

- mukana on myös kutsun esimerkki. Huomioi että se on kovin "epästandardi"
- koko hässäkän suorittaminen kestaa noin 8 ms.
**
BASH on todella epäsopiva ohjelmointiin. Mutta onneksi BASH:illa ei tarvitsekaan ohjelmoida vaan yksinomaan käyttää sitä sovellus-ohjelmien kutsumiseen. Koska BASH noudattaa omaa kieroutunutta logiikkaansa niin mikäli sillä haluaa tehdä tehokkaan skriptin täytyy hyväksyä BASH pomoksi ja itse toimia vain juoksupoikana. Jolloin päädytään siihen että parhaita BASH-koodereita ovat vasta-alkajat ja idiootit.

Myös BASH:in tekstinkäsittelyn huonoutta valitetaan. Mutta ensinnäkin BASH:illa ei käsitellä tekstiä vaan tekstinkäsittelyyn on tarkoitus käyttää siihen tatkoitettuja sovellus-ohjelmia. Toisekseenkin kyllä kaikki tekstinkäsittelyn perus-toiminnot löytyvät BASH:inkin käskyistä mutta lisäksi seuraavankaltaisia muuttujienkin kanssa toimivia "käskyjä" löytyy ziljoonia:

Koodia: [Valitse]
[[ eaaabc =~ aa ]] && echo jees # onko jälkimmäinen edellisen osa.
[[ aaabc =~ ^aa ]] && echo jees # alkaako edellinen jälkimmäisellä
[[ bcaaa =~ aa$ ]] && echo jees # loppuuko edellinen jälkimmäisellä

[[ ! abac =~ aa ]] && echo jees  # eihän vain edellisen sisällä ole jälkimmäistä
[[ ! bcaa =~ aa$ ]] && echo jees # eihän vain edellinen lopu jälkimmäiseen
[[ ! bcaa =~ ^aa ]] && echo jees # eihän vain edellinen ala jälkimmäisellä

[[ $(echo dddaaggggaasss | grep aa.*aa) ]] && echo jees # onko tekstijonossa kirjainryhmää: määrätty teksti[mitä tekstiä hyvänsä]määrätty teksti
[[ $(echo gg aasss | grep -w gg) ]] && echo jees        # onko tekstijonossa gg siten että sen vieressä ei ole aakkonumeroa (siis muita merkkejä voi olla)

echo 'Marker11234567890Marker2' | grep -Po '(?<=Marker1).*(?=Marker2)' # tulostaa tekstin joka on hakuavaimien välissä - jos kumpaakin avainta ei ole niin mitään ei tulostu
echo 'Marker11234567890Marker2' | grep -Po '(?<=Marker1).*'            # tulostaa tekstin joka on hakuavaimen edessä   - jos avainta ei ole niin mitään ei tulostu
echo 'Marker11234567890Marker2' | grep -Po '.*(?=Marker2)'             # tulostaa tekstin joka on hakuavaimen perässä  - jos avainta ei ole niin mitään ei tulostu
**
Aikoinaan aloin etsiä netistä kuinka BASH:illa tarkistetaan ennen matemaattista operaatiota onko lasku-lausekkeessa yhtämonta avaavaa ja sulkevaa sulkua. Kun yhteisö alkoi ratkaista ongelmaa muodosti ratkaisu aluksi kymmeniä rivejä. Ajan mittaann esitettiin jatkuvasti lyhyempiä skriptejä kunnes lopulta yksi tajuton esitti että seuraava mielipuolinen skripti muodostaa vain yhden rivin ja samalla se on nopea:
[[ $(tr -dc '\[' <<< "lauseke" | awk '{ print length; }') -ne $(tr -dc '\]' <<< "lauseke" | awk '{ print length; }') ]] && echo 'sulut epätasapainossa'
**
Yksi toteutus kaksi-ulotteisesta matriisista; tässä vaiheessa kylläkin vain periaatteen toimivuuden varmistus. Tehtävä on käyttökelvottomaksi vanhentunut mutta mielenkiintoinen ja se saattaa johtaa johonkin:

Koodia: [Valitse]
#!/bin/bash
function tulosta_matriisi () {
for n in $(eval echo -e \${$1[*]\n}§); do echo -ne ${n/§/\\n}' '; done | column -t 
}

a=(sin17 .2 3§.4 .5 6e8§ -7 8*8 \$!) # yksi menetelmä kaksiulotteisen matriisin kirjoittamiseksi sillä Linuxissahan ei selaista ole
                                    # siis §:llä merkitään että siirrytään täyttämään seuraavaa riviä. Nuo funktiot ja käskyt ovat mukana
                                    # siksi että näkee voiko niitä liittää mukaan - funktiot ratkaistaan toisaalla.
tulosta_matriisi a

« Viimeksi muokattu: 24.01.15 - klo:13.52 kirjoittanut petteriIII »

tathhu

  • Käyttäjä
  • Viestejä: 33
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #179 : 07.01.15 - klo:20.09 »
Moi, olen luonut pienen skriptin, joka symlinkkaa Kuvat-kansion jne kotikansiosta, joka on SSD'llä, normaalille, pyörivälle kiintolevylle. Se on kuitenkin "sidottu" siihen, että käyttiksen/kansioiden pitää olla suomen kielellä. Miten saisin järkevämmin toteutettua sen niin, että symlinkkaus onnistuu, oli kielenä mikä tahansa? Siis niin, että kotikansion "normaali" rakenne ei muutu.

Tällä hetkellä on näin:

ln -s [sijainti]/Kuvat /home/user/Kuvat
jne

E: lisää juttua;
Osaisko joku potkaista oikeaan suuntaan tässä:
Tarkoituksena olisi luoda skripti, josta saa valittua että asennetaan vaikka Libreoffice PPA'sta, päivitetään paketit ja asennetaan suljetut ajurit. Eli suora "lista" josta saa valita tehtäviä juttuja ja ne sitten suoritetaan.. Ei toimi pää yhtään.
« Viimeksi muokattu: 07.01.15 - klo:20.14 kirjoittanut Tathoo »
Ubuntu LTS läppärissä ja desktopissa, taskussa Jolla.

@ Tampere.