Kirjoittaja Aihe: BASH - Muuttuja joka tarkoittaisi vain joitakin numeroita?  (Luettu 2388 kertaa)

Dost

  • Käyttäjä
  • Viestejä: 725
    • Profiili
Tervehdys! Miten luoda yksi muuttuja joka tarkoittaisi mitä tahansa numeroa vaikkapa 1-5 tai vain joitakin esim. 2,3,5?

Eli pitäisi saada siistimmin ja helpommin tehtyä tätä samaa:
Koodia: [Valitse]
#!/bin/bash

lause=$(cat tiedosto.txt)

if [[ $lause == "tässä on numero 1" ]] || [[ $lause == "tässä on numero 2" ]] || [[ $lause == "tässä on numero 3" ]] || [[ $lause == "tässä on numero 4" ]] || [[ $lause == "tässä on numero 5" ]]
    then
    echo "yahoo!"
fi

exit


Tavoite on saada se näyttämään noin tälläiseltä:

Koodia: [Valitse]
#!/bin/bash

num="1 || 2 || 3 || 4 || 5"
lause=$(cat tiedosto.txt)

if [[ $lause == "tässä on numero $num" ]]
    then
    echo "yahoo!"
fi

exit

Mutta miten tehdään tuo "num"-muuttuja oikealla tavalla?
« Viimeksi muokattu: 19.11.21 - klo:22.32 kirjoittanut Dost »

SuperOscar

  • Käyttäjä
  • Viestejä: 3993
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: BASH - Muuttuja joka tarkoittaisi vain joitakin numeroita?
« Vastaus #1 : 19.11.21 - klo:22.52 »
En kyllä äkkiseltään keksi ”nättiä” ratkaisua Bashille, koska ilmeisesti ( | ) -notaatio ei toimi if-lauseissa.

Zsh:ssa onnistuu kahdellakin tavalla, joko numeroita etsien tai vaihtoehtoja etsien:

Koodia: [Valitse]
#!/bin/zsh

setopt extended_glob

while read lause; do
    # etsi numero väliltä 1–5
    [[ $lause == "tässä on numero "<1-5> ]] && print jahuu
    # etsi vaihtoehto 1, 3 tai 5
    [[ $lause == "tässä on numero "(1|3|5) ]] && print jahuu
done

Muoks: Sen verran lisäisin, että

Koodia: [Valitse]
lause=$(cat tiedosto.txt)
on Bashissakin paremmin:

Koodia: [Valitse]
lause=$(<tiedosto.txt)
Mutta minun käyttämäni while read -silmukka on sikäli parempi, että silloin luettavan tiedoston voi antaa uudelleenohjauksena komentoriviltä ja sitä luetaan rivi kerrallaan.
« Viimeksi muokattu: 19.11.21 - klo:23.02 kirjoittanut SuperOscar »
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

SuperOscar

  • Käyttäjä
  • Viestejä: 3993
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: BASH - Muuttuja joka tarkoittaisi vain joitakin numeroita?
« Vastaus #2 : 20.11.21 - klo:10.18 »
Yön yli mietittyäni totesin, että case-lauseellahan tuo onnistuu, tosin hieman säätäen.

Koodia: [Valitse]
#!/bin/bash

while read lause; do
    # tämä vain jotta näkee alkuperäisen rivin
    echo $lause
    lause=${lause##*numero }
    case $lause in
        (1|3|5)  echo jahuu
                    ;;
        (2|4|6)  echo jihuu
                    ;;
    esac
done

”lause=${lause##*numero }” poistaa yksinkertaisesti riviltä kaiken ennen numeroa, koska vaihtoehdot pitää antaa kokonaisina (= eivät voi sisältää *-osia).
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11

Dost

  • Käyttäjä
  • Viestejä: 725
    • Profiili
Vs: BASH - Muuttuja joka tarkoittaisi vain joitakin numeroita?
« Vastaus #3 : 20.11.21 - klo:14.06 »
Yön yli mietittyäni totesin, että case-lauseellahan tuo onnistuu, tosin hieman säätäen.

Koodia: [Valitse]
#!/bin/bash

while read lause; do
    # tämä vain jotta näkee alkuperäisen rivin
    echo $lause
    lause=${lause##*numero }
    case $lause in
        (1|3|5)  echo jahuu
                    ;;
        (2|4|6)  echo jihuu
                    ;;
    esac
done

”lause=${lause##*numero }” poistaa yksinkertaisesti riviltä kaiken ennen numeroa, koska vaihtoehdot pitää antaa kokonaisina (= eivät voi sisältää *-osia).

Jep, kiitos! Korvaan siis if:in case:lla. Just sopivasti mun tarkoitukseen nuo ";;" -väkäset näyttävät korvaavan elif:inkin.

Zsh on mulle uusi konsepti, enkä taida ymmärtää voiko sen ja bash:in sekoittaa samassa skriptissä.

Jere Sumell

  • Käyttäjä
  • Viestejä: 721
  • Talous, Hallinto ja Markkinointi (AMK, 2017),B.B.A
    • Profiili
    • Tietokone-blogi
Vs: BASH - Muuttuja joka tarkoittaisi vain joitakin numeroita?
« Vastaus #4 : 20.11.21 - klo:22.57 »
Viitaten SuperOscarin vastaukseen tuosta bash-shellin taulukoista, niin on totta, että [] -notaatio ei toimi, mutta mitenkäs --threads -parametri, äkkiseltään katsoin tuosta varmistukseksi hakukoneelta, niin tässä suora linkki artikkeliin, jossa käsitellään juuri alkuperäisen kysyjän esittämään ongelmaan ratkaisua perusteissa:

https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays

Samassa artikkelissa on esimerkki, miten viitataan johonkin tiettyyn alkioon, on tuossa näköjään taulukon iterointikin, ja sitten alkioiden lisääminen taulukkoon (array populating)

Lisään vielä UNIX-historiasta, että noissa ensimmäisen sukupolven shelleissä ei ollut muuttujia, esimerkiksi ensimmäisessä Thompson Shellissä, joka on Ken Thompsonin käsialaa, ja muistaakseni sitä käytettiin vähän yli 1970-luvun puoliväliin asti.

Noista toisen sukupolven shelleistä varmaan Bourne on ensimmäisiä, joissa oli jonkinlainen alkeellinen taulukointi, tai viittausjärjestelmä taulukon kaltainen, mutta bash on käsittääkseni paljon myöhemmin julkaistu, niin kyllä varmaan kaikissa nykyisissä Linux-koneissa käytössä olevat shellit omaavat taulukkorakenteen.
« Viimeksi muokattu: 20.11.21 - klo:23.06 kirjoittanut Jere Sumell »
Free Internet and  people for humans all over the globe!

(Profiilikuvassa oma valokuvani GIMPissä editoituna Disney Classic-väripaletin väreihin ja muunnettuna bittikartta-tiedostosta vektorigrafiikaksi.)

SuperOscar

  • Käyttäjä
  • Viestejä: 3993
  • Ocatarinetabellatsumtsum!
    • Profiili
    • Legisign.org
Vs: BASH - Muuttuja joka tarkoittaisi vain joitakin numeroita?
« Vastaus #5 : 21.11.21 - klo:17.02 »
Viitaten SuperOscarin vastaukseen tuosta bash-shellin taulukoista, niin on totta, että [] -notaatio ei toimi, mutta mitenkäs --threads -parametri, äkkiseltään katsoin tuosta varmistukseksi hakukoneelta, niin tässä suora linkki artikkeliin, jossa käsitellään juuri alkuperäisen kysyjän esittämään ongelmaan ratkaisua perusteissa:

Eikö tässä ollut kysymys enemmän vaihtoehtojen antamisesta mahdollisimman kätevästi kuin varsinaisesti taulukoista? Eli tuo alkuperäinen ongelmarivi:

Koodia: [Valitse]
if [[ $lause == "tässä on numero 1" ]] || [[ $lause == "tässä on numero 2" ]] || [[ $lause == "tässä on numero 3" ]] || [[ $lause == "tässä on numero 4" ]] || [[ $lause == "tässä on numero 5" ]]
…on ongelmallinen vain koska on pakko toistaa koko ”lause”? Taulukko tai vastaava on sinänsä yksi mahdollinen ratkaisutapa, mutta kun Bashissa ei ole  (?) myöskään operaattoria jäsenyyden tarkistamiseksi, sekään ei käy.

Pythonissa voi tehdä vaikka näin:

Koodia: [Valitse]
if lause in [f'tässä on numero {n}' for n in range(1, 6)]:
Nätti ei ole tuokaan mutta välttää sentään koko lauseen tuskallisen uudelleenkirjoittamisen!

Muoks: Ja nyt kun asiaa vielä ajattelen, toimiihan Bashissa sentään (( … )) -syntaksi kuten Zsh:ssakin, joten tämäkin kävisi:

Koodia: [Valitse]
lause=${lause##*numero }
(( lause >= 1 && lause <= 5 )) && echo numero väliltä 1–5

Tosin sillä edellytyksellä, että rivin lopussa varmasti on kelvollinen kokonaisluku!
« Viimeksi muokattu: 21.11.21 - klo:17.06 kirjoittanut SuperOscar »
pöytäkone 1, kannettavat 1–3: Debian GNU/Linux 12; pöytäkone 2: openSUSE Tumbleweed; NUC: openSUSE Leap 15.5; RPi 1: FreeBSD 13.2-RELEASE; RPi 2: LibreELEC 11