Skip to main content Link Menu Expand (external link) Document Search Copy Copied
UKOS Lab 5

Skrypty basha pt.2


Na poprzednich zajęciach poznaliśmy podstawy skryptowania. Dzisiaj poznamy dalsze podstawy skryptowania, czyli funkcje, pętle i może zrobimy kilka bardziej życiowych zadanek

Pętle while

W języku C mogliście mieć już pętle while, do while i for. W skryptach basha są one całkiem podobne, ale - jak już zdążyliśmy się przyzwyczaić - z dziwną składnią. Poniższa pętla wykonuje się tak długo, jak warunek jest spełniony. Więc na przykład pętla while [ true ] będzie się wykonywać w nieskończoność.

while [ warunek ]
do
    cośtam
done

dla przykładu:

#!/bin/bash
licznik=10
while [ $licznik -gt 0 ]
do
    echo obejscie petli nr. $licznik
    ((licznik--))
done

Krótka analiza poniższego wyniku wskazać może, że nasz kod nie ma zbyt wiele sensu.

obejscie petli nr. 10
obejscie petli nr. 9
obejscie petli nr. 8
obejscie petli nr. 7
obejscie petli nr. 6
obejscie petli nr. 5
obejscie petli nr. 4
obejscie petli nr. 3
obejscie petli nr. 2
obejscie petli nr. 1

Zadanie na 30 sekund

Popraw kod, żeby obejscia pętli liczyły się od 1 do 10

Pętla until

Składniowo identyczna do pętli while, ale wykonuje się tak długo, jak warunek nie jest spełniony. Aby najprościej zobrazować:

#!/bin/bash
licznik=10
until [ $licznik -le 0 ]
do
    echo obejscie petli nr. $licznik
    ((licznik--))
done

oraz:

#!/bin/bash
licznik=10
while [ $licznik -gt 0 ]
do
    echo obejscie petli nr. $licznik
    ((licznik--))
done

dają identyczne wyniki.

Pętle for

Pętla for w bashu działać może już zupełnie inaczej niż znana z C, a bardziej jak wykorzystywany w nowszych wersjach C++pętla foreach. Tutaj pętli podajemy serię argumentów, a ona wykonuje się nam tyle razy, ile podamy jej elementów.

for <var> in $zmienna
do
    cokolwiek
done
#!/bin/bash

lista="mango pineapple papaya"
for owoc in $lista
do
        echo Owoc: $owoc
done

i wynik powyższego, godnego inżyniera kawałka kodu:

michal@MacBook-Air-3 skrypty % ./s1.sh   
Owoc: mango
Owoc: pineapple
Owoc: papaya

W razie czego, niespokojnych uspokoję, znana nam wszystkim pętla for również działa:

#!/bin/bash

for ((i=0;i<10;i++))
do
	echo obejscie: $i
done

Ważna uwaga: w wypadku pętli for-each (tego fora, którego omawialiśmy jako pierwszego) pętla będzie wykonywać się na dowolnej podanej liście, więc możemy na przykład podać tam wynik polecenia find, albo $@, pętla również zadziała.

Case

Porównanie case do znanego z C switcha jest nieuniknione:

case $zmienna in
    przypadek1) instrukcja;;
    przypadek2 | przypadek3) instrukcja;;
    *) instrukcja dla każdego innego przypadku;;
esac

Warto zwrócić uwagę na trzecią linię powyższego przykładu. Takie zastosowanie pozwala nam na wykorzystanie jednej instrukcji dla kilku przypadków.

Funkcje

#!/bin/bash

nazwa_funkcji(){
        #zawartość_funkcji
}
nazwa_funkcji   #wywołanie funkcji

Do funkcji możemy podawać również argumenty. Działa to dokładnie w ten sam sposób, w jaki podawanie argumentów do skryptu, z tą różnicą, że argumenty podawane są po wywołaniu wewnątrz skryptu, nie z wiersza poleceń:

#!/bin/bash
funkcja(){
        echo Podano argument: $1
}

funkcja 123

Zadania do laboratorium

  1. Napisz skrypt wyświetlający, który będzie sprawdzał, czy przekazano do niego przynajmniej 5 argumentów numerycznych, a jeśli tak, to doda je wszystkie do siebie i wydrukuje wynik na terminalu
  2. Napisz skrypt kopiujący do katalogu Documents/copied pliki podane jako argumenty. Jeśli podany zostanie jeden argument, to przekopiuje wszystkie pliki o podanym jako argument rozszerzeniu z katalogów podrzędnych do Documents/copied
  3. Napisz skrypt dodający do pliku baza.txt wartości podane jako argumenty bądź przy użyciu read. Plik baza.txt ma posiadać 4 kolumny: Imię, nazwisko, płeć i wiek.