HyppÀÀ sisÀltöön

đŸ‘©â€đŸ”Ź Curium

Listat

Ennen kuin siirrymme viimeiseen Einsteinium-osuuteen, harjoitellaan vielÀ hieman listoja. Listat ovat tÀrkeitÀ, koska niitÀ kÀytetÀÀn usein silmukoiden yhteydessÀ. Listoja kÀsitellÀÀn usein myös argumentteina skripteille. On kovin tyypillistÀ, ettÀ sinun pitÀÀ tavalla tai toisella parsia kaikkia argumentteja, eli: $@, jonka osatekijöitÀ ovat $1, $2, $3, jne. Alla olevissa tehtÀvissÀ tÀhÀn tutustutaan parin rautakoodatun, helpomman esimerkin kautta.

Funktiot

Listojen lisÀksi on syytÀ opetella funktioiden kÀyttöÀ. Funktiot auttavat pitÀmÀÀn koodisi modulaarisena ja helposti luettavana. Funktiot ovat myös hyvÀ tapa vÀlttÀÀ toistoa koodissasi.

Funktiot ovat myös hyvÀ tapa testata koodiasi, koska voit testata yksittÀisiÀ funktioita erikseen. TÀmÀ on erityisen hyödyllistÀ, jos koodisi on monimutkaista ja sisÀltÀÀ paljon reunaehtoja.

TehtÀvÀt

TehtÀvÀ: Pilkulla erottelu

Luo skripti, joka tulostaa luvut 1-10 pilkulla eroteltuna. Skriptin pitÀÀ alkaa nÀin:

pilkkuerotellut.sh
#!/bin/bash
numbers=({1..10})

Lopputuloksena tulisi tulostaa:

🐳 stdout
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Vihje 1

Sijoita vÀliaikaiseen muuttujaan jotain, mitÀ seuraava tulostaa:

printf ", %s" "${numbers[@]}"
Vihje 2

Huomasit kaiketi, ettÀ yllÀ neuvottu komento jÀttÀÀ komennon alkuun pilkun ja vÀlilyönnin. Voit jÀttÀÀ nÀmÀ kaksi ensimmÀistÀ merkkiÀ, eli , tulostamatta kÀyttÀmÀllÀ ${parameter:offset} parameter expansion syntaksi:

echo ${muuttuja:2}
TehtÀvÀ: PizzatÀytteet

Luo skripti, jonka alussa mÀÀritellÀÀn rautakoodatut muuttujat alla olevan pizza.sh-esimerkin mukaisesti. Huomaa, ettÀ nimeÀ, ikÀÀ ja suosikkitÀytteitÀ pitÀÀ voida muuttaa. TÀytteitÀ on aina vÀhintÀÀn kaksi.

pizza.sh
#!/bin/bash
name='Black Knight'
age=42
fav_toppings=("egg" "sausage" "spam")

Tavoite on tulostaa seuraava lause:

🐳 stdout
Black Knight is 42 years old and likes pizza with egg, sausage, and spam.

Huomaa, ettĂ€ tĂ€ytteiden tulee olla pilkkueroteltuja kahden viimeisen vĂ€lissĂ€ kuuluu olla sana "and". Toiseksi viimeisen tĂ€ytteen perĂ€ssĂ€ saa joko olla pilkku tai ei - pÀÀtĂ€ itse (eli ns. Oxford comma 🧐).

Vihje

Kenties helpoin ratkaisu ymmÀrtÀÀ on string concatenation-tyyli, jossa ainekset ynnÀtÀÀn merkkijonoon. KÀytÀ for-silmukkaa, jossa rakennat pilkkuerotellun tÀytelistan yksi tÀyte kerrallaan. Huomaa, ettÀ tehtÀvÀn voi ratkaista myös aivan toisin.

for ingredient in "${fav_toppings[@]}"; do
    # IMPLEMENT if-else string concatenation here.

    n_toppings=$((n_toppings-1))
done

echo "${name} is ${age} years old and likes pizza with ${comma_topping}."
TehtÀvÀ: PÀivÀmÀÀrÀn analysointi

Luo skripti, joka analysoi skriptin ajopÀivÀstÀ seuraavat asiat:

  • Pariton vai parillinen pĂ€ivĂ€mÀÀrĂ€
  • Onko vuosi karkausvuosi
  • Kuinka monta pĂ€ivÀÀ on jouluaattoon?

KÀytÀ apuna funktioita, jotta koodi pysyy modulaarisena ja helposti luettavana. VÀltÀ pitkÀÀ "wall of text" -tyylistÀ koodia. Koodin runko voi myötÀillÀ esimerkiksi alla olevaa rakennetta:

dateinfo.sh
#!/bin/bash

# Define functions here
is_odd() {
    local today
    local number

    today=$1
    number= # IMPLEMENT

    # IMPLEMENT
    echo Something
}

# ... more functions here ...

# Wrapper function
main() {
    # Declare
    local default_date
    local today

    # Assign
    default_date=$(date +%Y-%m-%d)
    today=${1:-$default_date}

    # Call
    is_odd "$today"
    # is_leap_year "$today"
    # n_days_till_xmas "$today"
}

main "$@"

SkriptiÀ voi jatkossa kutsua argumentilla tai ilman. Alla kaksi esimerkkiÀ, joista alempi on ajettu 7. helmikuuta 2025.

đŸ–„ïž Bash
./runbash.sh sripts/dateinfo.sh 1600-02-29
🐳 stdout
[INFO] TÀnÀÀn on 1600-02-29
[INFO] PĂ€ivĂ€mÀÀrĂ€ on pariton. 🩄
[INFO] Karkausvuosi! 366 pĂ€ivÀÀ! 🎉
[INFO] PĂ€iviĂ€ jouluaattoon: 299 🎅
đŸ–„ïž Bash
./runbash.sh sripts/dateinfo.sh
🐳 stdout
[INFO] TÀnÀÀn on 2000-02-29
[INFO] PĂ€ivĂ€mÀÀrĂ€ on pariton. 🩄
[INFO] Karkausvuosi! 366 pĂ€ivÀÀ! 🎉
[INFO] PĂ€iviĂ€ jouluaattoon: 299 🎅
LisÀhaastetta?

Validoi pÀivÀmÀÀrÀ, jonka kÀyttÀjÀ antaa argumenttina. Voit esimerkiksi tarkistaa, ettÀ se noudattaa muotoa yyyy-mm-dd, ja ettÀ date-binÀÀri saa sen parsittua (eli ei palauta error return codea).

VielÀ lisÀÀ lisÀhaastetta?

Voit halutessasi toteuttaa itsellesi lisÀhaasteena testejÀ. TÀmÀ vaatisi, ettÀ esimerkiksi virheherkkÀ karkausvuoden logiikka on testattuna kohtalaisen systemaattisesti. TÀmÀ vaatii, ettÀ funktio is_leap_year palauttaa exit coden: 1 jos vuosi on karkausvuosi ja 0 jos ei. TÀmÀ exit code voidaan sitten tarkistaa testissÀ.

test_leap_year() {
    is_leap_year "$1" 0
    local result=$?
    local expected=$2
    if (( result != expected )); then echo "Failed $1 (${result})"; exit 1; fi
}

TÀmÀn jÀlkeen voit ajaa testejÀ esimerkiksi ennen main-funktion kutsua:

test_leap_year 1600-01-01 1
test_leap_year 1700-01-01 0
test_leap_year 2023-01-01 0
test_leap_year 2024-01-01 1
test_leap_year 2025-12-31 0
test_leap_year 2026-01-01 0
test_leap_year 2027-01-01 0
test_leap_year 2028-01-01 1
main "$@"

TÀmÀ on kuitenkin lisÀhaaste. Jos tÀmÀ tuntuu mahdottomalta, keskity muuhun.

TehtÀvÀ: Swap

Luoda ohjelma, joka auttaa sinua tilanteessa, jossa olet vahingossa kirjoittanut kahden eri tiedoston sisÀllöt ristiin. Toisin sanoen haluat vaihtaa tiedostot pÀikseen. Miten tÀmÀ onnistuu?

KÀyttö (kontin sisÀllÀ):

🐳 Bash
echo "I think I'm A" > b.txt   # note wrong content
echo "I think I'm B" > a.txt
/app/scripts/swap.sh tiedosto1.txt tiedosto2.txt
cat a.txt
🐳 stdout
I think I'm A
Vihje

KÀytÀ komentoa mktemp avuksesi. Tutustu sen ohjeisiin: Ubuntu Manuals: mktemp.