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

Whig

  • Käyttäjä
  • Viestejä: 184
  • puppu-generaattori
    • Profiili
    • localhost
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #240 : 10.10.18 - klo:09.35 »
Koodia: [Valitse]
list-urls.sh linkit.txt > linkit.html

Kiitän.
Tämä antoi tällaisen herjan:
bash: ./scripti.sh: /bin/sh^M: bad interpreter: No such file or directory

Tosin minulla on pieni epäillys, että tämä johtuu siitä että copy/pastesin scriptin windows koneella tikulle tiedostoon.
Tuo on joskus aikaisemminkin aiheuttanut ongelmia jotka on saanut dos2unix:lla ratkaistua mutta sitä ei tuossa kyseissä koneessa ollut joten joudun testaamaan uudelleen myöhemmin.
--
Instagram  <- Saa seurata ei ole pakko.
Blogi, kotisivu mikä lie...

nm

  • Käyttäjä
  • Viestejä: 12897
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #241 : 10.10.18 - klo:11.03 »
Tämä antoi tällaisen herjan:
bash: ./scripti.sh: /bin/sh^M: bad interpreter: No such file or directory

Tosin minulla on pieni epäillys, että tämä johtuu siitä että copy/pastesin scriptin windows koneella tikulle tiedostoon.

Kyllä. Vaatii dos2unixin tai vastaavan korjausoperaation CR-merkkien poistamiseen rivinvaihdoista. Pitäisi onnistua myös tr:llä:

Koodia: [Valitse]
tr -d '\r' < scripti.sh > korjattuscripti.sh

Whig

  • Käyttäjä
  • Viestejä: 184
  • puppu-generaattori
    • Profiili
    • localhost
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #242 : 11.10.18 - klo:08.37 »
Tämä antoi tällaisen herjan:
bash: ./scripti.sh: /bin/sh^M: bad interpreter: No such file or directory

Tosin minulla on pieni epäillys, että tämä johtuu siitä että copy/pastesin scriptin windows koneella tikulle tiedostoon.

Kyllä. Vaatii dos2unixin tai vastaavan korjausoperaation CR-merkkien poistamiseen rivinvaihdoista. Pitäisi onnistua myös tr:llä:

Koodia: [Valitse]
tr -d '\r' < scripti.sh > korjattuscripti.sh

Jees. Täytyy ottaa tulevaisuutta varten tuo tr rivi talteen. Sain tällä kertaa onneksi iPhonen kautta yhteyden nettiin ja sain copy/pastettua tuon scriptin ubuntu puolella. Scripti toimi ja teki juuri sen mitä pitikin joten kiitoksia taas kerran.
--
Instagram  <- Saa seurata ei ole pakko.
Blogi, kotisivu mikä lie...

sigfrid

  • Käyttäjä
  • Viestejä: 4
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #243 : 27.10.18 - klo:17.41 »
Moi,

tuli tenkkapo.  Pitäisi korvata positioarvo toisesta tiedostosta kaikilta riveiltä,  jos vastaava position arvo on ensimmäisessa tiedostossa 9.  Esimerkki

Tiedosto 1:
1221110091211219000121

Tiedosto 2:
1212210011200220000222

Ensimmäisen tiedoston 9. positio tulisi arvoon 1 ja 16. positio arvoon 0.  Tiedostot ovat kooltaan suuria ja identtiset rivimääriltään ja-pituudeltaan.  Voin tietenkin muuttaa rivien merkit sarakkeiksi lisäämällä erottimet merkkien väliin.



nm

  • Käyttäjä
  • Viestejä: 12897
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #244 : 27.10.18 - klo:20.32 »
@sigfrid:

Kuulostaa sen verran hankalalta ongelmalta, että kannattaa ottaa joku Bashia monipuolisempi kieli käyttöön. Vaikka Python, tai mikä tuntuu itselle helpoimmalta.

Whig

  • Käyttäjä
  • Viestejä: 184
  • puppu-generaattori
    • Profiili
    • localhost
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #245 : 04.01.19 - klo:13.33 »
Saan lähetetty sähköpostia komentoriviltä sendemail:lla OK ja saan lähetettyä HTML muotoisia sähköposteja myös joihin saan liitteeksi kuvan mutta mitenköhän sen saisi sisällytettyä itse viestiin?

Tarkoitus olisi siis lähettää sähköposteja joissa on kuva viestissä HTML:n seassa <img src="kuva.jpg"> mutta en millään saa päähäni miten saisin tämän tehtyä. Tiedostonahan tuon saa helposti mukaan -a kuva.jpg:llä mutta tällöin se näkyy viestin lopussa erillisenä liitteenä.
--
Instagram  <- Saa seurata ei ole pakko.
Blogi, kotisivu mikä lie...

nm

  • Käyttäjä
  • Viestejä: 12897
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #246 : 04.01.19 - klo:15.06 »
Tarkoitus olisi siis lähettää sähköposteja joissa on kuva viestissä HTML:n seassa <img src="kuva.jpg"> mutta en millään saa päähäni miten saisin tämän tehtyä. Tiedostonahan tuon saa helposti mukaan -a kuva.jpg:llä mutta tällöin se näkyy viestin lopussa erillisenä liitteenä.

Voit viitata viestin HTML-koodissa liitteenä olevaan kuvaan CID:llä, kuten täällä on esitetty: https://stackoverflow.com/a/17981118

Koodia: [Valitse]
sendmail -t <<EOT
TO: XXX@YYY.com
FROM: <TEST_IMAGE@YYY.com>
SUBJECT: Embed image test
MIME-Version: 1.0
Content-Type: multipart/related;boundary="XYZ"

--XYZ
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-15">
</head>
<body bgcolor="#ffffff" text="#000000">
<img src="cid:part1.06090408.01060107" alt="">
</body>
</html>

--XYZ
Content-Type: image/jpeg;name="sathy.jpg"
Content-Transfer-Encoding: base64
Content-ID: <part1.06090408.01060107>
Content-Disposition: inline; filename="sathy.jpg"

$(base64 sathy.jpg)
--XYZ--
EOT



Kuvan voi myös enkoodata suoraan img-tagiin base64-muodossa, mutta kaikki sähköpostiohjelmat eivät tue sitä. Toinen laajemmin yhteensopiva ratkaisu on ladata kuva jollekin nettipalvelimelle ja viitata siihen koko osoitteella.

Whig

  • Käyttäjä
  • Viestejä: 184
  • puppu-generaattori
    • Profiili
    • localhost
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #247 : 07.01.19 - klo:11.53 »
Voit viitata viestin HTML-koodissa liitteenä olevaan kuvaan CID:llä, kuten täällä on esitetty: https://stackoverflow.com/a/17981118


Kiitoksia vinkistä mutta nyt pätkii sen verran pahasti päässä, että en tajua miten homma toimii ja onnistuuko käyttämälläni sendemail:lla samoin, kuin sendmail:lla.
Pitänee lukea tuo ohje vielä pariin otteeseen ja lähteä testailemaan sillä tuskin tuo niin vaikea on, kuin miltä se luettuna näyttää.

Itse viesti tökätään --XYZ rivin väliin ja "<img src="cid:part1.06090408.01060107" alt="">" src:llä viitataan myöhemmin (--XYZ:n jälkeen) "Content-ID: <part1.06090408.01060107>" kohdassa olleeseen .jpg:n jonka polku kerrotaan "Content-Disposition: inline; filename="sathy.jpg"" kohdassa.
« Viimeksi muokattu: 07.01.19 - klo:11.55 kirjoittanut Whig »
--
Instagram  <- Saa seurata ei ole pakko.
Blogi, kotisivu mikä lie...

nm

  • Käyttäjä
  • Viestejä: 12897
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #248 : 07.01.19 - klo:12.21 »
Itse viesti tökätään --XYZ rivin väliin ja "<img src="cid:part1.06090408.01060107" alt="">" src:llä viitataan myöhemmin (--XYZ:n jälkeen) "Content-ID: <part1.06090408.01060107>" kohdassa olleeseen .jpg:n jonka polku kerrotaan "Content-Disposition: inline; filename="sathy.jpg"" kohdassa.

Content-Type-rivin parametrilla name ja Content-Disposition-rivin parametrilla filename määritellään liitteen tiedostonimi, jonka sähköpostiohjelma sitten osaa näyttää. Epäilen, että Content-Disposition-rivi on sähköpostin tapauksessa turha, tai inlinen sijaan se voisi yhtä hyvin olla attachment. Sähköpostiohjelmat esittävät molemmat samalla tavalla liitteinä.

Joka tapauksessa lähdetiedoston polkua ei määritellä viestissä, eikä sitä anneta sendmailin käsiteltäväksi. Sen sijaan tiedoston sisältö enkoodataan base64-muotoon ja sisällytetään viestiin rivillä:

Koodia: [Valitse]
$(base64 sathy.jpg)
Eli jos kuvatiedosto sijaitsee vaikkapa käyttäjän kotihakemiston Kuvat-kansiossa, sen voisi syöttää base64:lle näin:

Koodia: [Valitse]
$(base64 "$HOME/Kuvat/kuva.jpg")

Lisäys: RFC2183:n mukaan "Content-Disposition: inline" määrittää, että liitteet tulisi esittää automaattisesti, kun viesti avataan. Enpä sitten tiedä, miten moni ohjelma oikeasti tekee eroa inline- ja attachment-asetuksen välillä...
« Viimeksi muokattu: 07.01.19 - klo:13.09 kirjoittanut nm »

petteriIII

  • Käyttäjä
  • Viestejä: 578
    • Profiili
Vs: Ohjeita shell-skriptaukseen (bash)
« Vastaus #249 : 12.05.19 - klo:09.51 »
Olen pitkään ihmetellyt päätteeni historian temppuilemista: esimerkiksi duplikaatit eivät poistu vaikka käskee, ja jokakerran saa pikkuisen ihmetellä että mitähän sieltä nyt tulee.

Luin netistä muutaman kommentin joita en purematta niele mutta ajateltavaa ne antaa:
- historia tykkää kyttyrää joistakin ei-ascii merkeistä
- kun historia alkaa temppuilla niin ainoa pätevä keino on tyhjentää historiatiedosto.

Tein siis historiatiedostosta kopion ja tyhjensin vanhan. Ainakin duplikaatit alkoivat poistua ja jotenkin toimintaan tuli jämäkkyyttä.

Apuahan tässä täytyy pyytää.

***

Tämmöistä tein:
Koodia: [Valitse]
Vanhankin .bash_history:n sai käyttöön kun poisti sen duplikaatit ulkoisella käskyllä:
cat ~/.bash_history | tac | awk '!a[$0]++' | tac > ~/koe . Ja koe-tiedoston tutkimisen jälkeen talletin sen .bash_history:n tilalle.

Samalla kirjoitin .bashrc:hen:
export HISTSIZE=100000
export HISTFILESIZE=100000

HISTCONTROL=ignoredups:erasedups
shopt -s histappend
PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"

Mutta myöntää täytyy että liian syvillä vesillä liikutaan.

***

 Kukaan ei kykene tekemään yhtäkään skriptiä jossa ei olisi parantamisen varaa - ja usein parantamista on paljon sillä pitkät ja hitaaat skriptit supistuvat nopeiksi muutaman sanan yksirivisiksi - mutta kannattaako sen vaatima työ on kyseenalaista - eikä niiden kehittämiseen kenenkään omat rahkeet riitä. Joten puhumalla skripteistä mitähyvänsä puhuu ilmanmuuta paljon myös palturia.

***

Väite etteivät BASH:in funktiot kykene palauttamaan parametrejaan on sinällään tosi. Useimmilla asian merkitys on hakusessa, mutta virtuooseilta on tahallinen ja ilkeämielinen unohdus että BASH osaa tehdä tuosta parametrin palauttamisesta turhaa. Ikuisesti on tunnettu seuraava esimerkki:
a=b;let $a=55;echo b -> tulostaa 55
Funktiomuotoon sovellettuna tämä on:
Koodia: [Valitse]
function koe () { let $1=55 ;}; koe a; echo $a
joka myös tulostaa 55
- siis passataan nimiparametri.
- $1 eteen lisätään joku käsky, esimerkiksi let, read, readarray, test, eval ...
- let toimii vain numeroiden kanssa.
- readarray toimii vähän erilailla kuin muut:
Koodia: [Valitse]
function koe () { readarray $1 < /boot/grub/grub.cfg ;}; koe a; printf "%s\n" "${a[@]}"

Väite kyvyttömyydestä palauttaa parametrejä ontuu muutenkin vähäsen sillä kun joku kirjoittaa näytölle - ei ole väliä  mikä - niin toinen voi käydä lukemassa sen sieltä; toiminta on erittäin nopea eikä se jätä näytölle jälkeä siitä että sitä on käytetty. Tosin se toimii ongelmitta vain kun tulostusta on yksi rivi mutta se riittääkin usein. Esimerkiksi
Koodia: [Valitse]
function koe () { echo töttöröö ;}; a=$(koe); echo $a           # toimii oikein
function koe () { cat /boot/grub/grub.cfg ;}; a=$(koe); echo $a # koko teksti menee yhdelle riville ja se on usein ongelmallista.

Ja aina voi funktiossakin kirjoittaa levylle ja pääohjelmassa käydä lukemassa sieltä. Keino on ihan ongelmaton ja se hidastaa toimintaa olemattoman vähän - ajatuskin on kyllä inhottava.

Nopeasti toimiva matriisin sorttausfunktio numero-arvoille
=====================================
- sort-ohjelma sorttaa mitä sille tulostetaan - on aivan sama tulostetaanko sille tiedosto vaiko matriisi.
- matriisia ei muodosteta uudestaan funktiossa, vaan pääohjelmassa käydään näytöltä lukemassa funktioon tulostus ja muodostetaan matriisi uudestaan senperusteella - sentakia kutsu on omituinen mutta toiminta on paljon nopeampaa.
- 1900 jäsenisen matriisin sorttauksessa kuluva aika on noin 60ms
 
#!/bin/bash
export LC_ALL=C # desimaalipiste on tällä sivulla piste eikä pilkku niinkuin normaalilla koodisivulla ->
                # desimaalit sorttautuvat oikein samoinkuin tieteellinen esitysmuoto kytkimellä -g.
Koodia: [Valitse]

function sorttaamatriisi () { declare | grep ^$1= | sed "s/$1=//;s/\s\[/\n/g" | cut -d= -f2 | tr -d \(\)[]\" | sort -g ;} # sort-käskyn parametreja saattaa joutua muuttamaan.

#mat=($(seq 10000;seq 10000))
mat=($(seq -5700 1.5 5700;seq -5700 1.0  5700)) # noin joka neljäs on duplikaatti ja niiden pitää löytyä
#echo matriisi sorttaamatta: ;echo ${mat[*]}
alkuhetki=$(date +%s.%N)
mat=($(sorttaamatriisi mat))
loppuhetki=$(date +%s.%N)
echo matriisi sortattuna: ; echo "${mat[*]}"
echo -n sorttaukseen kulunut aika sekuntia: ; echo $loppuhetki-$alkuhetki | bc
(( ${#mat[*]} > 1 )) && echo kysessä on tosiaan matriisi
# duplikaattien lukumäärä
singlikaatit=$(echo "${mat[*]}" |  tr ' ' '\n' | sort | uniq | wc -w)
kaikki=$(echo "${mat[*]}" | wc -w)
echo duplikaatteja $((2*($kaikki-$singlikaatit)))
export LC_ALL=
- BASH:in sorttausrutiinit syövät usein duplikaatteja ja testatessa on syytä varmistaa että duplikaatteja ei syödä - esimerkiksi laskemalla ne ja vertaamalla siihen paljonko niitä pitäisi olla.
- jos luulee työskentelevänsä matriisin kanssa niin kannattaa testata työskenteleekö matriisin vaiko samannimisen muuttujan kanssa - jossa matriisin koko sisältö on on yhtenä tekstijonona. 
- nimenomaan kannattaa huomioida ettei tässä funktiossa tarvita eval-käskyä.
- tämä kykenee sorttaamaan vain numeroita - ja yksinkertaista tekstiä.
- toki parametrin voisi "palauttaakin". Mutta aikaa se vain tuhraa.

***

Verkkosivuilla esitetystä BASH-koodista ei juuri koskaan skriptin kokeilemisen takia tarvitse tehdä skripti-tiedostoa eikä edes lausetta #!/bin/bash välttämättä tarvita. Riittää kun maalaat koodin kokonaisuudessaan ja painat ctrl-c. Siten avaa pääte painamalla ctrl-alt-t ja sitten paina ctrl-shift-v . Lopuksi kannattaa painaa enter. Näyttö ei ole ihan siisti mutta asia selviää kyllä.
« Viimeksi muokattu: 17.06.19 - klo:17.40 kirjoittanut petteriIII »