Uniwersytet w Białymstoku
Wydział Matematyki i Informatyki
Instytut Informatyki
Materiały bazowe do zajęć z przedmiotu:
Systemy operacyjne
Laboratorium nr 08
Temat:
Zmienne tablicowe, pętle for, while i until
mgr Adam Bonda
Białystok 2008
Cel laboratorium: Zapoznanie si
ę
z u
ż
yciem p
ę
tli
for
,
while
,
until
w poł
ą
czeniu z
rozszerzon
ą
arytmetyk
ą
parametrów ich wywołania i zastosowaniem zmiennych
tablicowych.
Podwójne nawiasy
(( wyrażenie ))
oraz podwójne nawiasy kwadratowe
[[ wyrażenie ]]
Podwójne nawiasy pozwalaj
ą
na bezpo
ś
rednie wprowadzanie bardziej zaawansowanych
formuł matematycznych na poziomie porówna
ń
komend strukturalnych (
if-then
) w
odró
ż
nieniu od polecenie test, które oferowało u
ż
ycie tylko prostych operacji
arytmetycznych.
Składnia
wyrażenie
mo
ż
e by
ć
zarówno matematycznym jak i porównawczym
wyra
ż
eniem.
$ cat skrypt.sh
#!/bin/bash
var_1=5
if (( $var_1 ** 2 > 20 ))
then
(( var_2 = $var_1 ** 2 ))
echo "Kwadratem liczby $var_1 jest $var_2"
fi
$ ./skrypt.sh
Kwadratem liczby 5 jest 25
Dozwolone jest stosowanie nast
ę
puj
ą
cych operatorów w wi
ę
kszo
ś
ci znanych ju
ż
z
poprzednich zaj
ęć
:
i++, i--, ++i, --i, !, ~, **, <<, >>, &, |, &&, ||
.
Podwójne nawiasy kwadratowe pozwalaj
ą
na u
ż
ycie zaawansowanych porówna
ń
ci
ą
gów
znaków. Porównywanie stringów zapisanych, jako wyra
ż
enia otoczone tymi symbolami
odbywa si
ę
podobnie jak w przypadku polecenia test. Symbol podwójnego nawiasu
kwadratowego zapewnia jednak skorzystanie z dodatkowej opcji, której polecenie test nie
posiada, porównywania wzorców. W porównywanym wzorcu mo
ż
liwe jest zdefiniowanie
wyra
ż
enia regularnego, które porównywane jest z ci
ą
giem znakowym.
$ cat skrypt.sh
#!/bin/bash
if [[ $SHELL == xt* ]]
then
echo "Używasz terminala $SHELL"
else
echo "Hmm, a mówiłem, żeby nie instalować nowych \"wynalazków\""
echo "ale z drugiej strony, może ten terminal zjada mniej zasobów?"
fi
Zmienne tablicowe
Powłoka
bash
umo
ż
liwia korzystanie z jednowymiarowych tablic. Nazywane s
ą
one
zmiennymi tablicowymi, poniewa
ż
mog
ą
przechowywa
ć
wi
ę
cej ni
ż
jedn
ą
warto
ść
. Ka
ż
da
warto
ść
indeksowana jest liczb
ą
całkowit
ą
, a indeks elementu tablicy umieszcza si
ę
w
nawiasach kwadratowych, jak podano w przykładzie ni
ż
ej:
TABLICA1[0]="wartość zerowego"
TABLICA1[1]=drugi
TABLICA1[2]=3
TABLICA1[4]=iv
Mo
ż
liwa jest inicjacja wielu elementów tablicy naraz:
TABLICA2=( "wartość zerowego" pierwszego [9]=numer iv )
Elementy tablicy rozdziela si
ę
spacjami i wylicza poczynaj
ą
c od elementu o indeksie
0
. Jak
wida
ć
powy
ż
szym przykładzie mo
ż
na tworzy
ć
elementy o konkretnym indeksie, poprzez
zadeklarowanie jego numeru w nawiasach klamrowych.
Odwołanie si
ę
do warto
ś
ci elementu zmiennej tablicowej mo
ż
liwe jest poprzez
zastosowanie wyra
ż
enia:
${nazwa_zmiennej_tablicowej[indeks]}
$ echo ${TABLICA2[0]}
wartość zerowego
Wy
ś
wietlony został element tablicy o indeksie zero
$ echo ${TABLICA2[3]}
Element o indeksie 3 nie istnieje, zwrócona wi
ę
c została warto
ść
pusta.
$ echo ${TABLICA2[9]}
numer
Element o indeksie 9, przechowuje warto
ść
„numer”.
$ echo ${TABLICA2[10]}
iv
Je
ś
li w tablicy zadeklarowano warto
ść
nie b
ę
d
ą
c
ą
kontynuacj
ą
poprzednich indeksów to
tworzone dalej elementy (bez podania numeru) indeksowane s
ą
kolejnymi liczbami
całkowitymi. W tym przypadku nie podanie indeksu warto
ś
ci „iv” spowodowało
automatyczne przydzielenie jej warto
ś
ci (
10
) wy
ż
szej o jeden ni
ż
indeks j
ą
poprzedzaj
ą
cy
(
9
).
U
ż
ycie zmiennych specjalnych, jako indeksów jest równie
ż
dozwolone np.:
${zmienna[*]}, "${zmienna[*]}", ${zmienna[@]}
.
$ echo ${TABLICA2[*]}
wartość zerowego pierwszego numer iv
Wy
ś
wietlone zostały wszystkie elementy tablicy
$ echo "${TABLICA2[*]}"
wartość zerowego|pierwszego|numer|iv
Wy
ś
wietlone zostały wszystkie elementy tablicy, a podwójne cytowania spowodowało
u
ż
ycie separatora zdefiniowanego zmienn
ą
systemow
ą
IFS
(ang. internal field separator).
Domy
ś
lnie powłoka
bash
, jako separatorów u
ż
ywa: spacji, tabulatora, znaku nowej linii.
Podobnie jak w przypadku zmiennych, zmienne tablicowe i ich elementy usuwa si
ę
poleceniem
unset
.
unset TABLICA2[9]
$ echo ${TABLICA2[*]}
wartość zerowego pierwszego iv
Usunięto element o indeksie 9.
$ echo ${TABLICA2[9]}
$ echo ${TABLICA2[10]}
iv
Warto
ść
elementu indeksowanego liczb
ą
9
jest pusta. Nie nast
ą
piła jednak reindeksacja
elementów i nast
ę
pny, w stosunku do usuni
ę
tego elementu, posiada w dalszym ci
ą
gu
indeks o numerze
10
.
unset TABLICA2
$ echo ${TABLICA2[*]}
Usuni
ę
ta została zmienna tablicowa i wszystkie jej elementy.
Instrukcja wyboru
case
Działanie komendy
case
jest podobne do konstrukcji warunkowej
if-then
. Jak sama
nazwa wskazuje dotyczy ona wyborów, a wi
ę
c okre
ś
lenia, który fragment kodu zostanie
wykonany na zasadzie sprawdzania przynale
ż
no
ś
ci testowanej warto
ś
ci do z góry
okre
ś
lonego zbioru.
Ogólna posta
ć
tej konstrukcji przedstawia si
ę
nast
ę
puj
ą
co:
case zmienna in
szablon1 | szablon2) komenda1;;
szablon3)
komenda2
komenda3
komenda3
;;
*) domyślne_komendy;;
esac
Po komendzie
case
, podawana jest warto
ść
, która ma by
ć
oceniana. Mo
ż
e to by
ć
zmienna, lub zdefiniowane słowo. Z oczywistych wzgl
ę
dów wstawia si
ę
tam zazwyczaj
nazw
ę
zmiennej – zwi
ę
ksza automatyczno
ść
konstrukcji. Je
ż
eli w słowie wyst
ę
puj
ą
spacje, to cało
ść
nale
ż
y otoczy
ć
znakami podwójnego cytowania. Kolejnymi elementami
case
s
ą
: słowo kluczowe
in
i lista opcji do wyboru.
Ka
ż
d
ą
z opcji umieszcza si
ę
w nowej linii i ko
ń
czy zamykaj
ą
cym nawiasem. Je
ż
eli shell
ustali zgodno
ść
zmiennej z którym
ś
z szablonów to wykonana zostanie komenda, b
ą
d
ź
lista wprowadzonych komend umieszczonych za danym ci
ą
giem szablonów, po czym
obsługa
case
jest ko
ń
czona.
W szablonach dozwolone jest stosowanie wyra
ż
e
ń
regularnych zawieraj
ą
cych metaznaki:
*
(dowolny napis)
?
(dowolny znak)
[...]
(okre
ś
lony zbiór znaków).
Konstrukcja
case
nie sprawdza, czy wszystkich szablonów pasuj
ą
cych do testowanego
słowa/zmiennej. Je
ś
li shell natrafi na pierwszy zgodny ze zmienn
ą
szablon to lista komend
po nim wyst
ę
puj
ą
cych jest wykonywana.
case "$1" in
*) echo "zgodność 1";;
*) echo "zgodność 2";;
esac
W powy
ż
szym przykładzie zostanie wi
ę
c wy
ś
wietlony tylko napis „zgodno
ść
1”.
case "$1" in
start|uruchom)
echo "$0 został wywołany z pierwszym argumentem:"
echo "\"start\" lub \"uruchom\""
stop|zatrzymaj)
echo "$0 został wywołany z pierwszym argumentem:"
echo "\"stop\" lub \"zatrzymaj\""
*)
echo "$0 został wywołany z pierwszym argumentem"
echo "nierozpoznawalnym przez składnię skryptu."
esac
Mo
ż
liwe jest poddawanie kilku szablonów alternatywnych (poprzez u
ż
ycie symbolu
podziału potoku
|
), przy których zostanie wykonany ten sam ci
ą
g instrukcji.
P
ę
tla
for
Powłoka
bash
oferuje dwa rodzaje p
ę
tli. Pierwszy z nich stanowi p
ę
tla
for
. Pobiera ona,
jako parametr, list
ę
napisów i dla ka
ż
dego, jeden raz wykonuje zadeklarowan
ą
składni
ę
.
Drugi rodzaj p
ę
tli stanowi
ą
polecenia
while
i
until
, które w odró
ż
nieniu od
for
pobieraj
ą
wyra
ż
enie warunkowe, jako parametr i wykonuj
ą
si
ę
tak długo, jak wyra
ż
enie jest
prawdziwe (w przypadku
while
), lub gdy jest fałszywe (w przypadku
until
).
Bash
poprzez struktur
ę
for umo
ż
liwia wykonywanie p
ę
tli iteracyjnej na zbiorze warto
ś
ci.
Ka
ż
da iteracja (powtórzenie) wykonuje tylko jeden raz okre
ś
lony zestaw instrukcji dla
ka
ż
dej warto
ś
ci zbioru przekazanej w postaci parametru.
Ogólna konstrukcja p
ę
tli
for
, któr
ą
obsługuje powłoka
bash
ma nast
ę
puj
ą
c
ą
posta
ć
:
for var in lista_słów
do
zestaw_instrukcji
done
lista_słów
przekazywana jest p
ę
tli w formie parametru po słowie kluczowym
in
,
poprzedzonym nazw
ą
zmiennej
var
. Podczas ka
ż
dej iteracji, zmienna var przechowuje
aktualn
ą
warto
ść
z listy. Pierwsza iteracja wykorzystuje pierwszy element listy, kolejna
drugi, trzeci i tak, i tak a
ż
do ostatniego.
Ci
ą
g instrukcji zawieraj
ą
cy zmienn
ą
var
, jaki ma zosta
ć
wykonany dla ka
ż
dego elementu
listy umieszcza si
ę
pomi
ę
dzy znacznikami
do
i
done
.
for i in $*
do
echo wartość argumentu: $i
done
Wywołanie powy
ż
szego skryptu z kilkoma parametrami zwróci warto
ś
ci tych parametrów
poprzedzone ci
ą
giem tekstowym.
for i in `ls *.sh`
do
echo $i
done
Jak wida
ć
na powy
ż
szych przykładach,
lista_słów
mo
ż
e by
ć
reprezentowan
ą
zmienn
ą
przechowuj
ą
c
ą
zbiór warto
ś
ci, lub mo
ż
e by
ć
po prostu list
ą
elementów wprowadzonych
przez u
ż
ytkownika, b
ą
d
ź
te
ż
wyprowadzonych za pomoc
ą
zewn
ę
trznej komendy. Ka
ż
dy
element mo
ż
e by
ć
cyklicznie wywoływany tylko raz, wraz z zestawem komend, a
ż
do
momentu, kiedy
lista_słów
zostanie wyczerpana.
Powłoka
bash
umo
ż
liwia tak
ż
e u
ż
ywanie konstrukcji p
ę
tli for w formie znanej z j
ę
zyka C:
for (( i=0; <= 5; i++ ))
do
echo $i
done
Konstrukcja
while
i
until
Inny rodzaj p
ę
tli stanowi
ą
komendy
while
i
until.
Blok polece
ń
obj
ę
ty działaniem p
ę
tli
while
jest wykonywany w kolejnych cyklach p
ę
tli tak długo, jak długo spełniony jest
warunek okre
ś
lony parametrem, wyst
ę
puj
ą
cym bezpo
ś
rednio po słowie
while
.
Ogólna konstrukcja p
ę
tli
while
, któr
ą
obsługuje powłoka
bash
ma nast
ę
puj
ą
c
ą
posta
ć
:
while komendy1
do
komendy2
done
Opisana konstrukcja powoduje wykonanie listy polece
ń
, okre
ś
lonym w powy
ż
szym zapisie
jako
komendy1
i warunkowe wykonanie polece
ń
komendy2
, obj
ę
tych działaniem p
ę
tli, które
zawarte s
ą
pomi
ę
dzy słowami kluczowymi
do
i
done
. Wykonywane s
ą
wi
ę
c najpierw
polecenia komendy1,a gdy zwrócenie warto
ś
ci 0 (true) warunkuje to wywołanie instrukcji
zawartych pomi
ę
dzy do i done. P
ę
tla jest wykonywana do momentu otrzymywania
warto
ś
ci 0, w przeciwnym razie jest ko
ń
czona.
while [ $1 ]
do
echo kod wyjścia: $? argumenty: $*
shift
done
Je
ż
eli podano niepust
ą
warto
ść
parametrów, to konstrukcja while wykonuje test ilo
ś
ci
argumentów, po czym wy
ś
wietla aktualn
ą
ich liczb
ę
. Dopóki zwracany z testu kod wyj
ś
cia
b
ę
dzie
0
(true) p
ę
tla b
ę
dzie si
ę
wykonywała. Zastosowanie wewn
ę
trznego polecenia
powłoki shift w bloku instrukcji uruchamianych po spełnieniu warunku – powoduj
ą
cego
przesuwanie parametrów w lewo i ich kasowanie – zmniejszaj
ą
cego z ka
ż
dym cyklem
liczb
ę
parametrów o jeden i obni
ż
aj
ą
cego numeracj
ę
zmiennych, powoduje,
ż
e p
ę
tla
b
ę
dzie wykonywała si
ę
do momentu anihilacji ostatniego argumentu, tj. wtedy, gdy test
zwróci warto
ść
ró
ż
n
ą
od zera (w tym wypadku 1).
Poł
ą
czenie polecenia
test
z konstrukcj
ą
while
równoznaczne jest u
ż
yciu konstrukcji
if-
then
.
Podczas uruchamiania procesów tworzone s
ą
tzw.
pidfile
, czyli pliki informuj
ą
ce o tym,
ż
e dany proces jest uruchomiony. Zazwyczaj przechowuj
ą
te
ż
one numer tego procesu.
Po zako
ń
czeniu działania programu, jego
pidfile
jest automatycznie kasowany.
Przy pomocy konstrukcji
while
mo
ż
emy sprawdza
ć
czy dane polecenie jeszcze działa i
warunkowa
ć
wykonywanie kolejnych opartych o wyniki działania poprzednich aplikacji:
while [ -f ~/program1/pidfile ]
do
sleep 10
done
P
ę
tla sprawdza istnienie pliku, je
ś
li zwrócona jest warto
ść
0
(true) to czeka 10 sek. i
ponownie dokonuje sprawdzenia. Konstrukcja ko
ń
czy działania w przypadku skasowania
pliku.
Je
ż
eli potrzebna jest odwrotne działaj
ą
ca p
ę
tla, tzn. je
ż
eli komenda ma by
ć
wykonana do
momentu otrzymania warto
ś
ci kodu wyj
ś
cia ró
ż
nego od
0
stosujemy konstrukcj
ę
until
:
until komendy1
do
komendy2
done
Dopóki kod wyj
ś
cia
komendy1
b
ę
dzie zwracał warto
ść
warto
ść
ró
ż
n
ą
od
0
blok polece
ń
komendy2
, b
ę
dzie wykonywany. Po osi
ą
gni
ę
ciu warto
ś
ci
0
, p
ę
tla zako
ń
czy swoje działanie.
until who | grep student1
do sleep 20
done
write student1 << MSG
-- zajecia z 21.01.2012 odwolane --
MSG
Dopóki u
ż
ytkownik nie zaloguje si
ę
do systemu p
ę
tl
ą
b
ę
dzie zawiesza
ć
działania na 20
sek. po czym uruchomia
ć
si
ę
ponownie. Kiedy polecenie zwróci warto
ść
0
(true) działanie
p
ę
tli zostanie przerwane, a znalezionemu w systemie u
ż
ytkownikowi przesłana zostanie
(za pomoc
ą
programu
write
) wiadomo
ść
znajduj
ą
ca si
ę
pomi
ę
dzy znacznikami
<< MS
G i
MSG
.
Zadanie 1
Napisa
ć
skrypt, który w zale
ż
no
ś
ci od tego, czy uruchomił go u
ż
ytkownik student, czy root
wy
ś
wietli powitalny napis. Dla u
ż
ytkownika jas i marysia zwróci dwa ró
ż
ne komunikaty, a
dla pozostałych u
ż
ytkowników wypisany b
ę
dzie napis,
ż
e nie s
ą
oni znani skryptowi.
Przetestowa
ć
działanie skryptu.
Zadanie 2
Napisa
ć
skrypt, który przy u
ż
yciu p
ę
tli
for
wy
ś
wietli list
ę
5 dowolnych imion z
poprzedzaj
ą
cym ich stałym tekstem.
Zadanie 3
Napisa
ć
skrypt, który ka
ż
de słowo zdania potraktuje, jako osobny element i wypisze go na
standardowym wyj
ś
ciu: "Lubie "programowa
ć
" w bash'u".
Zadanie 4
Napisa
ć
skrypt o działaniu, jak z zadania 2, z t
ą
ró
ż
nic
ą
,
ż
eby czytanie listy było ze
zmiennej.
Zadanie 5
Napisa
ć
skrypt, który przy pomocy p
ę
tli b
ę
dzie wy
ś
wietlał wszystkie dane z pliku
"
im_nazw
", który trzeba uprzednio stworzy
ć
i wprowadzi
ć
dowolne dane trzech osób
(ka
ż
da w nowej linii) wg wzoru: Imi
ę
Nazwisko
Zadanie 6
Napisa
ć
skrypt który sprawdzi i wypisze, które z plików katalogu domowego s
ą
katalogami,
a które zwykłymi plikami. Zastosowa
ć
tylko jedn
ą
p
ę
tl
ę
.
Zadanie 7
Napisa
ć
skrypt, który przy u
ż
yciu p
ę
tli for wypisze dziesi
ęć
kolejnych warto
ś
ci.
Zadanie 8
Napisa
ć
skrypt, w którym dwie zmienne b
ę
d
ą
zmienia
ć
warto
ś
ci przeciwbie
ż
nie: pierwsza
od A do B, a druga od B do A (A i B s
ą
cyframi). Zmiana w ka
ż
dym cyklu dla obydwu
zmiennych.
Zadanie 9
Przepisa
ć
działanie skryptu z zadania 7 z u
ż
yciem p
ę
tli
while
Zadanie 10
Napisa
ć
skrypt wykonuj
ą
cy to samo zadanie przy u
ż
yciu konstrukcji for
while [ $1 ]
do
echo kod wyj
ś
cia: $? argumenty: $*
shift
done
Zadanie 11
Za pomoc
ą
konstrukcji
until
wyliczy
ć
wszystkie warto
ś
ci z okre
ś
lonym krokiem, od
zadeklarowanej do zera.
Zadanie 12
Napisa
ć
skrypt, który dla ka
ż
dej z warto
ś
ci od 5 do 0 wykona mno
ż
enie ka
ż
dej z tych
warto
ś
ci przez cyfry od 1 do 3. Wszystkie dane wy
ś
wietli
ć
na ekranie i zapisa
ć
do pliku z
poziomu skryptu.
Zadanie 13
Napisa
ć
skrypt, który dla ka
ż
dej linii pliku
/etc/passwd
wypisze wszystkie jej elementy .
Przykładowy wynik działania skryptów::
student:x:1000:1004:student:/home/student:/bin/bash
student
x
1000
..
itd.
Zadanie 14
Napisa
ć
skrypt, który dla zmiennej tablicowej (stworzy
ć
zmienn
ą
składaj
ą
c
ą
si
ę
z 7
elementów) wy
ś
wietli liczb
ę
elementów przechowuj
ą
cych przez tablic
ę
, a nast
ę
pnie
indeksy i przyporz
ą
dkowane im warto
ś
ci elementów, oraz wszystkie elementy nieparzyste.
Zadanie 15
Napisa
ć
skrypt, który wypisze nazwy wszystkich plików katalogu domowego małymi
literami, a katalogów du
ż
ymi.