14, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta


Rozdział 14.
Programowanie
w języku powłoki


Rick McMullin

W tym rozdziale:

Trzy poprzednie rozdziały mówiły o używaniu najpopularniejszych powłok linuxowych. Teraz przyjrzymy się wbudowanym w nie interpretowanym językom programowania.

Poniższy rozdział omawia podstawy pisania skryptów w języku powłoki, ze zwróceniem uwagi na różnice pomiędzy językami wbudowanymi w poszczególne interpretery. Poruszone zostaną następujące tematy:

Każde nowe polecenie przedstawione w tym rozdziale poparte jest krótkim przykładem, który ma na celu ułatwienie zrozumienia zasad jego stosowania.

Tworzenie i uruchamianie programów powłoki

W najprostszym przypadku program powłoki (nazywany dalej również skryptem) to plik, który zawiera jedno lub więcej poleceń powłoki. Takich programów można używać w sposób podobny do aliasów, by oszczędzić sobie częstego wpisywania identycznych sekwencji poleceń. Możliwe jest również pisanie prostych programów wymagających interakcji użytkownika, na przykład instalujących inne programy.

Aby stworzyć skrypt powłoki, powinieneś utworzyć nowy plik (na przykład za pomocą edytora tekstów) i umieścić w nim polecenia, które mają zostać wykonane. Załóżmy, że w Twoim systemie plików zamontowany jest CD-ROM. Jest on montowany podczas uruchamiania systemu. Jeśli zmienisz dysk CD-ROM podczas pracy, musisz nakazać systemowi odczytanie nowego drzewa katalogów. Można to uzyskać przez odmontowanie, a następnie ponowne zamontowanie CD-ROM-u. Odpowiednia sekwencja poleceń ma postać:

umount /dev/cdrom
mount -t iso9660 /dev/cdrom /cdrom

Zamiast wpisywać oba te polecenia, można stworzyć krótki program w języku powłoki, nazwać go np. nowycd, i posługiwać się nim.

Istnieje kilka metod wykonywania programu zapisanego w pliku. Jedną z nich jest nadanie plikowi prawa do wykonywania, na przykład następującym poleceniem:

chmod +x nowycd

Możesz teraz wywołać skrypt nowycd poprzez wpisanie jego nazwy w wierszu poleceń.

0x01 graphic

Plik będący programem powłoki musi znajdować się w którymś z katalogów wchodzących w skład ścieżki przeszukiwania, w przeciwnym przypadku interpreter nie będzie potrafił go odnaleźć. Ponadto jeśli używasz interpretera tcsh, pierwszy wiersz musi zaczynać się od znaku #.

Innym sposobem wykonania programu zapisanego w pliku jest uruchomienie powłoki, dla której program został napisany, z nazwą pliku podaną jako parametr wywołania, np.

tcsh nowycd

Trzecią metodą jest użycie polecenia . (kropka) w powłokach pdksh i bash lub source w tcsh. Polecenie to powoduje wykonanie poleceń zawartych w pliku podanym jako parametr, np.

. nowycd

w przypadku bash i pdksh czy też

source nowycd

w przypadku tcsh.

Oto inna sytuacja, w której prosty skrypt może zaoszczędzić nieco czasu. Załóżmy, że pracujesz nad trzema plikami w danym katalogu i codziennie robisz ich kopię zapasową na dyskietce, wydając polecenia:

mount -t msdos /dev/fd0 /a
cp plik1 /a
cp plik2 /a
cp plik3 /a

Łatwiejszym sposobem będzie umieszczenie tych poleceń w pliku (o nazwie np. backup) i wywoływanie go jako programu powłoki jednym z podanych wcześniej sposobów.

0x01 graphic

Jeśli chcesz używać pliku backup jako programu powłoki, powinieneś przypisać mu prawo do wykonywania i umieścić go w jednym z katalogów wchodzących w skład ścieżki przeszukiwania.

Używanie zmiennych

Tak jak w każdym języku programowania, użycie zmiennych w programach powłoki jest sprawą bardzo ważną. Z niektórymi ze zmiennych powłoki (na przykład PATH czy PS1) miałeś już okazję się zapoznać, wiesz również, jak można nadać im wartość. W tym podrozdziale dowiesz się, jak można tworzyć własne zmienne i posługiwać się nimi w programach powłoki.

Nadawanie wartości zmiennej

W powłokach bash i pdksh przypisanie odbywa się poprzez podanie nazwy zmiennej, znaku równości i wartości zmiennej, np.:

licznik=5

W tcsh należy do tego celu użyć polecenia set, np.:

set licznik=5

0x01 graphic

Jeśli używasz interpretera bash lub pdksh, upewnij się, że przed i po znaku równości nie występują spacje, ponieważ spowodują one błędną interpretację polecenia. Nie ma to znaczenia w przypadku powłoki tcsh.

Zauważ, że nie zachodzi potrzeba deklarowania zmiennych przed ich użyciem, jak ma to miejsce w takich językach, jak C czy Pascal, ponieważ w języku powłoki nie występuje pojęcie typów. Oznacza to, że tej samej zmiennej można używać zarówno do przechowywania tekstów, jak i liczb całkowitych. Tekst możesz przypisać zmiennej w taki sam sposób, jak liczbę całkowitą, np.:

imie=Piotr

w przypadku powłok bash i pdksh lub

set imie=Piotr

w przypadku tcsh.

Odczytywanie wartości zmiennej

Potrafisz już przypisać zmiennej wartość; teraz trzeba jakoś ją odczytać. Można to zrobić przez wpisanie nazwy zmiennej poprzedzonej znakiem dolara; aby na przykład wypisać wartość zmiennej licznik na ekranie, można wydać polecenie:

echo $licznik

0x01 graphic

Jeśli znak dolara zostałby pominięty, na ekranie zostałoby wyświetlone słowo licznik.

Parametry pozycyjne
i inne zmienne wewnętrzne
powłoki

Parametry pozycyjne to specjalne zmienne powłoki, w których przechowywane są parametry wywołania przekazywane do programu. Pierwszy z parametrów programu zapisany jest w zmiennej o nazwie 1, drugi - 2 itd. Są to nazwy zarezerwowane, nie można więc tworzyć własnych zmiennych o takich identyfikatorach. Dostęp do wartości przechowywanych w tych zmiennych można uzyskać poprzedzając ich nazwy znakiem $, podobnie jak ma to miejsce w przypadku pozostałych zmiennych.

Poniższy przykładowy program wymaga podania dwóch parametrów, które następnie wyświetlane są w odwrotnym porządku:

#program odwroc - wyswietla parametry w odwrotnej kolejnosci
echo "$2" "$1"

Jeśli wywołasz taki program w następujący sposób:

odwroc kota ogonem

wynik będzie następujący:

ogonem kota

Istnieje jeszcze kilka zmiennych wewnętrznych powłoki, bez znajomości których trudno się obejść. Tabela 14.1 zawiera najważniejsze z nich wraz z krótkimi opisami.

Tabela 14.1. Wewnętrzne zmienne powłoki

Zmienna

Znaczenie

$#

Zawiera ilość argumentów przekazanych z wiersza poleceń do programu powłoki

$?

Zawiera wartość zwróconą przez ostatnio wykonane polecenie lub program

$0

Zawiera pierwszy wyraz wpisanego polecenia (czyli zazwyczaj nazwę skryptu)

$*

Zawiera wszystkie argumenty wywołania ($1 $2 $3 ...)

"$@"

Zawiera wszystkie argumenty wywołania, każdy z osobna ujęty w cudzysłów ("$1" "$2" "$3" ...)

Cudzysłowy

Użycie różnego rodzaju cudzysłowów oraz znaku \ (backslash) ma zasadnicze znaczenie dla programowania w języku powłoki. Służą one do ukrywania niektórych symboli przed interpreterem poleceń.

Podwójny cudzysłów jest „najsłabszy”. Jeśli tekst jest otoczony pojedynczym cudzysłowem, ignorowane są wszystkie znaki białe w nim zawarte, ale nadal interpretowane są wszystkie pozostałe symbole specjalne. Jeśli na przykład chcesz przypisać tekst Witam Cie do zmiennej pozdrowienie, powinieneś wydać polecenie:

pozdrowienie="Witam Cie" lub
set pozdrowienie="Witam Cie",

zależnie od tego, jakiego interpretera używasz.

Dzięki cudzysłowowi cały tekst Witam Cie traktowany jest jako jeden wyraz. Jeśli nie zostanie on otoczony cudzysłowem, bash i pdksh wygenerują komunikat o błędzie, natomiast tcsh podstawi tekst Witam, ignorując dalszą część wiersza.

„Najsilniejszy” jest cudzysłów pojedynczy (`). Ukrywa on przed interpreterem wszystkie symbole specjalne. Stosowany jest, gdy dany tekst nie jest przeznaczony do interpretacji przez powłokę, ale przez inny program.

Jeśli chciałbyś w zmiennej pozdrowienie zamieścić również identyfikator użytkownika, powinieneś wydać polecenie:

pozdrowienie="Witam Cie $LOGNAME"

dla interpreterów bash i pdksh lub

set pozdrowienie="Witam Cie $LOGNAME"

dla tcsh.

Spowoduje ono podstawienie do zmiennej pozdrowienie tekstu Witam Cie root (o ile jesteś zalogowany jako root). W przypadku otoczenia tekstu pojedynczym cudzysłowem, nie uzyskałbyś pożądanego efektu, ponieważ wartość zmiennej LOGNAME nie zostałaby podstawiona. Zmienna pozdrowienie zawierałaby tekst Witam Cie $LOGNAME.

0x01 graphic

Zmienna LOGNAME to zmienna wewnętrzna powłoki, zawierająca identyfikator użytkownika, który uruchomił daną powłokę.

Trzecią metodą ukrywania symboli specjalnych przed interpreterem poleceń jest użycie symbolu \. Ukrywa on przed interpreterem jeden dowolny znak (ten, który następuje zaraz po symbolu \). Polecenie z pierwszego przykładu może więc być również zapisane jako

pozdrowienie=Witam\ Cie (dla powłok bash i pdksh) lub
set pozdrowienie=Witam\ Cie dla powłoki tcsh.

Oto inny przykład użycia tego symbolu:

cena_dysku=\$5.00 (dla powłok bash i pdksh) lub
set cena_dysku=\$5.00 dla powłoki tcsh.

Teraz ukryty przed interpreterem został znak dolara, co zapobiega podstawieniu w miejsce $5 piątego parametru pozycyjnego (ponieważ jest to nazwa jednej ze zmiennych wewnętrznych). Gdyby nie zastosowano symbolu \, interpreter poleceń w miejsce sekwencji znaków $5 próbowałby podstawić wartość piątego parametru pozycyjnego, a jeśli parametr taki nie byłby zdefiniowany, wstawiony zostałby ciąg pusty, czyli zmienna cena_dysku otrzymałaby wartość .00.

0x01 graphic

W powyższym przykładzie można również użyć pojedynczego cudzysłowu.

Odwrócony cudzysłów (`) pojedynczy spełnia nieco inną funkcję. Pozwala on na użycie rezultatu działania jakiegoś polecenia w innym poleceniu. Przykładowo, jeśli chcesz przypisać zmiennej katalog listę plików w bieżącym katalogu, powinieneś wydać polecenie

katalog=`ls`

dla powłoki bash i pdksh lub

set katalog=`ls`

dla tcsh.

Polecenie to spowoduje wykonanie polecenia ls, zapisując wyniki jego działania do zmiennej katalog. Jak przekonasz się w podrozdziale dotyczącym instrukcji iteracji, możliwość taka bywa bardzo użyteczna.

Polecenie test

Polecenie test używane jest w powłokach bash i pdksh do warunkowego wykonywania części programu. Stosuje się je zazwyczaj do sprawdzania warunków będących częścią instrukcji warunkowej lub warunków wejścia do albo wyjścia z pętli. Jego składnia jest następująca:

test wyrażenie

lub

[ wyrażenie ]

W poleceniu tym użyć można kilku operatorów. Dzielą się one na cztery grupy: operatory całkowite (działające na liczbach całkowitych), tekstowe, plikowe i logiczne. Operatory całkowite i tekstowe pełnią w zasadzie te same funkcje, różnią się tylko typem danych, na których operują. Zebrane one zostały w tabeli 14.2.

Tabela 14.2. Operatory całkowite polecenia test

Operator

Znaczenie

int1 -eq int2

Zwraca wartość logiczną True (prawda), jeśli argument int1 jest równy int2

int1 -ge int2

Zwraca wartość logiczną True (prawda), jeśli argument int1 jest większy lub równy int2

int1 -gt int2

Zwraca wartość logiczną True (prawda), jeśli argument int1 jest większy niż int2

int1 -le int2

Zwraca wartość logiczną True (prawda), jeśli argument int1 jest mniejszy lub równy int2

int1 -lt int2

Zwraca wartość logiczną True (prawda), jeśli argument int1 jest mniejszy niż int2

int1 -ne int2

Zwraca wartość logiczną True (prawda), jeśli argument int1 nie jest równy int2

Tabela 14.3 przedstawia operatory tekstowe (służące do manipulowania łańcuchami znaków) obsługiwane we wszystkich trzech powłokach.

Tabela 14.3. Operatory tekstowe polecenia test

Operator

Znaczenie

tekst1 = tekst2

Zwraca wartość logiczną True (prawda), jeśli tekst1
jest identyczny z tekst2

tekst1 != tekst2

Zwraca wartość logiczną True (prawda), jeśli tekst1
nie jest identyczny z tekst2

tekst

Zwraca wartość logiczną True (prawda), jeśli wartość zmiennej tekst jest zdefiniowana

-n tekst

Zwraca wartość logiczną True (prawda), jeśli tekst
ma długość większą od 0

-z tekst

Zwraca wartość logiczną True (prawda), jeśli tekst
ma długość równą 0

Operatory plikowe używane są np. do sprawdzania, czy plik istnieje, bądź też do sprawdzania, jaki rodzaj pliku został podany jako parametr. Zebrano je w tabeli 14.4.

Tabela 14.4. Operatory plikowe polecenia test

Operator

Znaczenie

-d nazwapliku

Zwraca wartość logiczną True (prawda), jeśli nazwapliku odnosi się do jest katalogu

-f nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku jest zwyczajnym plikiem

-r nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku może być czytany przez proces

-s nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku ma długość większą od 0

-w nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku może być zapisywany przez proces

-x nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku jest wykonywalny

Operatory logiczne używane są do łączenia dwóch lub więcej operatorów różnego typu lub do zaprzeczenia pojedynczego operatora. Tabela 14.5 zawiera dostępne operatory logiczne.

Tabela 14.5. Operatory logiczne polecenia test

Operator

Znaczenie

! wyrażenie

Zwraca wartość logiczną True (prawda), jeśli wyrażenie
nie jest prawdziwe

wyr1 -a wyr2

Zwraca wartość logiczną True (prawda), jeśli oba wyrażenia wyr1 i wyr2 są prawdziwe

wyr1 -o wyr2

Zwraca wartość logiczną True (prawda), jeśli któreś z wyrażeń wyr1 lub wyr2 jest prawdziwe

Odpowiedniki polecenia test w powłoce tcsh

W powłoce tcsh nie jest dostępne polecenie test. Wszystkie wymienione wyżej funkcje obsługiwane są za pomocą wyrażeń, w których można stosować operatory prawie identyczne jak te występujące w języku C. Wyrażenia są najczęściej używane z instrukcjami if oraz while, o których będzie mowa w podrozdziałach „Instrukcje warunkowe” oraz „Instrukcje iteracyjne”.

tcsh obsługuje takie same typy operatorów, jak powłoki bash i pdksh: operatory całkowite, tekstowe, plikowe i logiczne. Wraz z krótkimi objaśnieniami zostały one przedstawione w poniższych tabelach.

Tabela 14.6. Operatory całkowite powłoki tcsh

Operator

Znaczenie

int1 >= int2

Zwraca wartość logiczną True (prawda), jeśli liczba int1
jest większa lub równa int2

int1 > int2

Zwraca wartość logiczną True (prawda), jeśli liczba int1
jest większa niż int2

int1 <= int2

Zwraca wartość logiczną True (prawda), jeśli liczba int1
jest mniejsza lub równa int2

int1 < int2

Zwraca wartość logiczną True (prawda), jeśli liczba int1
jest mniejsza niż int2

Tabela 14.7. Operatory tekstowe obsługiwane w powłoce tcsh

Operator

Znaczenie

tekst1 == tekst2

Zwraca wartość logiczną True (prawda), jeśli tekst1
jest taki sam jak tekst2

tekst1 != tekst2

Zwraca wartość logiczną True (prawda) jeśli tekst1
nie jest identyczny z tekst2

Tabela 14.8. Operatory plikowe obsługiwane w powłoce tcsh

Operator

Znaczenie

-r nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku można odczytywać

-w nazwapliku

Zwraca wartość logiczną True (prawda), jeśli możliwy jest zapis do pliku nazwapliku

-x nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku może być wykonywany

-e nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku istnieje

cd. na następnej stronie

Tabela 14.8. cd. Operatory plikowe obsługiwane w powłoce tcsh

Operator

Znaczenie

-o nazwapliku

Zwraca wartość logiczną True (prawda), jeśli właścicielem pliku nazwapliku jest bieżący użytkownik

-z nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku ma długość większą od 0

-f nazwapliku

Zwraca wartość logiczną True (prawda), jeśli plik nazwapliku jest zwyczajnym plikiem

-d nazwapliku

Zwraca wartość logiczną True (prawda), jeśli nazwa nazwapliku odnosi się do katalogu

Tabela 14.9. Operatory logiczne obsługiwane w powłoce tcsh

Operator

Znaczenie

! wyrażenie

Zwraca wartość logiczną True (prawda), jeśli wyrażenie
nie jest prawdziwe

wyr1 && wyr2

Zwraca wartość logiczną True (prawda), jeśli oba wyrażenia wyr1 i wyr2 są prawdziwe

wyr1 || wyr2

Zwraca wartość logiczną True (prawda), jeśli któreś z wyrażeń wyr1 lub wyr2 jest prawdziwe

Instrukcje warunkowe

Każdy z omawianych interpreterów obsługuje dwa rodzaje instrukcji warunkowych: if oraz case. Są one używane do wykonywania części programu w zależności od tego, czy pewne warunki są spełnione, czy też nie. Ich składnia różni się w zależności od powłoki.

Polecenie if

Wyrażenie typu if-then-else obsługiwane jest we wszystkich trzech powłokach. Umożliwia ono sprawdzanie w programach powłoki nawet bardzo skomplikowanych warunków. Jego składnia jest taka sama w powłokach bash i tcsh:

if [ warunek ]
then
polecenia
elif [ warunek2 ]
then
polecenia
else
polecenia
fi

0x01 graphic

Wyrażenia elif i else są opcjonalne. Powłoki bash i pdksh w większości wyrażeń złożonych do zasygnalizowania końca wyrażenia używają jego odwróconej nazwy. Koniec wyrażenia if sygnalizowany jest więc słowem fi.

Instrukcja elif to skrót od else if (w przeciwnym przypadku, jeżeli...). Jest ona wykonywana tylko wtedy, jeśli żaden z warunków w poprzedzających ją poleceniach if i elif nie był spełniony. Polecenia zawarte w bloku po instrukcji else zostaną wykonane w przypadku, gdy żaden z warunków w poprzedzającym ją poleceniu if i poleceniach elif nie był spełniony.

W powłoce tcsh polecenie if może mieć dwie różne formy. Pierwsza z nich jest odpowiednikiem składni używanej w pozostałych powłokach:

if (warunek1) then
polecenia
else if (warunek2) then
polecenia
else
polecenia
endif

Druga forma jest formą uproszczoną, pozwalającą na sprawdzenie tylko jednego warunku. Jeśli jest on prawdziwy, wykonywane jest pojedyncze polecenie, w przeciwnym przypadku nic się nie dzieje. Składnia tej formy polecenia if jest następująca:

if (warunek) polecenie

Zaoszczędza ona programiście nieco pisania w przypadku prostych instrukcji warunkowych.

Oto przykład użycia instrukcji warunkowej if w powłokach bash i pdksh. Sprawdza on, czy w bieżącym katalogu znajduje się plik o nazwie .profile.

if [ -f .profile ]
then

echo "Plik .profile znaleziony w biezacym katalogu."
else
echo "Nie znaleziono pliku .profile."
fi

Ten sam przykład napisany dla interpretera tcsh wygląda następująco:

#
if ( { -f profile } ) then
echo "Plik .profile znaleziony w biezacym katalogu."
else
echo "Nie znaleziono pliku .profile."
endif

0x01 graphic

Zauważ, że w przypadku skryptu tcsh pierwszy wiersz zaczyna się od znaku #. Znak ten jest wymagany, by interpreter tcsh rozpoznał plik jako program powłoki.

Polecenie case

Polecenie case pozwala na sprawdzenie, czy wartość zmiennej pokrywa się z jednym z kilku wzorców, i wykonanie jednego z bloków kodu w zależności od tego, z którym z nich się zgadza. Jest ono nieco bardziej zaawansowane w porównaniu ze swoimi odpowiednikami w językach C i Pascal, ponieważ pozwala na używanie w charakterze wzorca tekstów, włącznie z symbolami specjalnymi, podczas gdy w wymienionych wcześniej językach można używać tylko typów całkowitych i wyliczeniowych.

Również w przypadku tego polecenia składnia dla powłok bash i pdksh jest jednakowa, a inna dla tcsh. Dla interpreterów bash i pdksh jest ona następująca:

case tekst in
tekst1)
polecenia;;
tekst2)
polecenia;;
*)
polecenia;;

esac

Wartość zmiennej tekst jest porównywana z wzorcami tekst1 i tekst2. Jeśli porównanie w którymś przypadku wypadnie pomyślnie, wykonywane są polecenia aż do podwójnego średnika. Jeśli tekst nie zgadza się ani z tekst1, ani z tekst2, wykonane zostaną polecenia w bloku za symbolem *. Jest to przypadek domyślny, gwiazdka symbolizuje dowolny tekst.

Odpowiednikiem polecenia case w interpreterze tcsh jest polecenie switch. Jego składnia jest podobna, jak w języku C:

switch (tekst)
case tekst1:
polecenia
breaksw
case tekst2:
polecenia
breaksw
default:
polecenia
breaksw
endsw

Mechanizm działania tego polecenia jest taki sam, jak polecenia case w powłokach bash i pdksh. Każdy tekst zapisany po słowie kluczowym case jest porównywany z wartością zmiennej tekst. Jeśli któreś porównanie wypadnie pomyślnie, wykonywany jest odpowiedni blok kodu, aż do napotkania słowa kluczowego breaksw. W przeciwnym przypadku wykonany zostanie blok instrukcji po słowie kluczowym default.

Poniżej zamieszczamy przykład użycia instrukcji case w interpreterach bash i pdksh. Sprawdza on, czy pierwszym argumentem przekazanym w wierszu poleceń jest -i lub -e. W pierwszym przypadku zlicza ilość wierszy pliku o nazwie podanej jako drugi parametr, zaczynających się na literę i. Jeśli pierwszym argumentem jest -e, program zlicza wiersze pliku podanego jako drugi argument, które zaczynają się na literę e. Jeśli pierwszym argumentem nie jest ani -i, ani -e, wówczas wyświetlany jest krótki komunikat o błędzie.

case $1 in
-i)
licz=`grep ^i $2 | wc -l`
echo "Ilosc wierszy zaczynajacych się na i w pliku $2 wynosi $licz"
;;
-e)
licz=`grep ^e $2 | wc -l`
echo "Ilosc wierszy zaczynajacych się na e w pliku $2 wynosi $licz"
;;
*)
echo "Nie rozpoznano opcji"
;;
esac

Ten sam przykład dla powłoki tcsh ma postać:

# Pierwszy wiersz musi zaczynać się od symbolu #
switch ( $1 )
case -i | i:
set licz = `grep ^i $2 | wc -l`
echo "Ilosc wierszy zaczynajacych się na i w pliku $2 wynosi $licz"
breaksw
case -e | e:
set licz = `grep ^e $2 | wc -l`
echo "Ilosc wierszy zaczynajacych się na e w pliku $2 wynosi $licz"
breaksw
default:
echo " Nie rozpoznano opcji"
breaksw
endsw

Instrukcje iteracyjne

Język powłoki udostępnia również kilka metod zapętlenia programu. Najczęściej używa się do tego celu pętli for. Oprócz niej istnieją również inne pętle (jak while oraz until), ale nie różnią się one zasadniczo od pętli for.

Pętla for

Pętla for pozwala na kilkukrotne wykonanie grupy poleceń. bash i pdksh obsługują dwa warianty instrukcji for.

Pierwszy z nich ma następującą składnię:

for zm1 in lista
do
polecenia
done

W tej formie polecenie for wykonywane jest dla każdej wartości z listy. Lista może być zmienną zawierającą słowa oddzielone spacjami albo też bezpośrednio podaną listą wartości. Podczas każdego przebiegu pętli zmiennej zm1 przypisywana jest kolejna wartość z listy, aż osiągnięty zostanie jej koniec.

Druga forma polecenia for ma składnię:

for zm1
do
polecenia
done

W tym przypadku pętla wykonywana jest dla każdego wyrazu zawartego w zmiennej zm1. Gdy użyta jest ta forma, interpreter przyjmuje, że zmienna zm1 zawiera wszystkie parametry pozycyjne, które zostały podane w wierszu poleceń. Zazwyczaj jest to równoznaczne z poniższym wyrażeniem:

for zm1 in "$@"
do
polecenia
done

Odpowiednikiem takiej pętli w powłoce tcsh jest pętla foreach. Ma ona składnię:

foreach nazwa (lista)
polecenia
end

Poniżej podano przykład zastosowania pętli for dla powłok bash i pdksh. Pobiera on jako parametry wywołania dowolną liczbę nazw plików tekstowych. Następnie wczytuje każdy z tych plików, zamienia w nim wszystkie małe litery na wielkie, a wynik zapisuje w pliku o nazwie takiej, jaką miał plik źródłowy, ale z rozszerzeniem .caps.

for plik
do
tr a-z A-Z < $plik >$plik.caps
done

Ten sam przykład dla interpretera tcsh ma postać:

#
foreach plik ($*)
tr a-z A-Z < $plik > $plik.caps
end

Pętla while

Pętla while to kolejna instrukcja iteracyjna dostępna w językach powłoki. Powoduje ona wykonywanie bloku programu tak długo, dopóki określony warunek jest prawdziwy. Jej składnia w interpreterach bash i pdksh jest następująca:

while wyrazenie
do
polecenia
done

W interpreterze tcsh należy stosować składnię:

while (wyrazenie)
polecenia
end

Przykładem zastosowania tej pętli może być program, który wypisuje na ekranie wszystkie argumenty wywołania, wraz z ich numerami. Oto wersja takiego programu dla bash i pdksh:

licz=1
while [ -n "$*" ]
do
echo "Parametr numer $licz: $1"
shift
licz=`expr $licz + 1`
done

Jak przekonasz się czytając podrozdział „Polecenie shift”, polecenie shift służy do przesuwania parametrów przekazanych z wiersza poleceń o jeden w prawo.

Wersja tego programu dla powłoki tcsh ma postać:

#
set licz = 1
while ( "$*" != "" )
echo "Parametr numer $licz: $1"
shift
set licz=`expr $licz + 1`
end

Pętla until

Pętla until jest bardzo podobna do pętli while, z tym że zostaje przerwana w momencie, gdy warunek jest spełniony (czyli dokładnie na odwrót niż w przypadku pętli while). W powłokach bash i pdksh składnia instrukcji until ma postać:

until wyrazenie
do
polecenia
done

Przykład podany dla pętli while można przepisać, używając pętli until, negując tylko warunek:

licz=1
until [ -z "$*" ]
do
echo "Parametr numer $licz: $1"
shift
licz=`expr $licz + 1`
done

Jedyną różnicą jest fakt, że z polecenia test usunięta została opcja -n (która sprawdzała, czy tekst ma długość różną od zera) i zastąpiona opcją -z, która sprawdza, czy tekst ma zerową długość.

W praktyce pętla ta nie ma wielkiego znaczenia, ponieważ każda pętla until może zostać zapisana za pomocą instrukcji while. Z tego również powodu w powłoce tcsh nie ma jej odpowiednika.

Polecenie shift

Wszystkie trzy omawiane powłoki obsługują polecenie shift, które przesuwa aktualne wartości parametrów pozycyjnych o jeden w lewo. Przykładowo, jeśli aktualnymi wartościami parametrów pozycyjnych są:

$1=-r $2=plik1 $3=plik2

to po wykonaniu polecenia shift będą one miały wartości:

$1=plik1 $2=plik2

Podając po poleceniu shift liczbę, można również przesunąć parametry o więcej niż jedną pozycję; na przykład by przesunąć parametry pozycyjne o dwie pozycje, należy wydać polecenie:

shift 2

Polecenie shift jest bardzo użyteczne, gdy wykorzystujesz w swoim programie kilka argumentów wywołania, na przykład różne opcje. Ponieważ zwykle są one przetwarzane w jakiegoś rodzaju pętli, wygodnie jest po obsłużeniu pierwszego z nich przesunąć wszystkie w lewo. Przykładowy skrypt spodziewa się dwóch opcji podanych w wierszu poleceń, po których następują odpowiednio nazwy pliku wejściowego i wyjściowego. Wczytuje następnie plik wejściowy, w którym zamienia wszystkie litery na wielkie, a wynik zapisuje w pliku wyjściowym. Skrypt działa w interpreterach bash i pdksh.

while [ "$1" ]
do
if [ "$1" = "-i" ] then
plikwe="$2"
shift 2
elif [ "$1"="-o" ]
then
plikwy="$2"
shift 2
else
echo "Program $0 nie rozpoznaje opcji $1"
fi
done

tr a-z A-Z $plikwe $plikwy

Polecenie select

Powłoka pdksh udostępnia bardzo użyteczne polecenie, którego nie obsługuje ani bash, ani tcsh. Jest to polecenie select. Od innych pętli różni się tym, że nie wykonuje bloku poleceń w zależności od tego, czy warunek jest spełniony, czy nie, ale służy głównie do generowania prostych menu tekstowych. Jego składnia jest następująca:

select pozycjamenu [in lista_pozycji]
do
polecenia
done

Nawiasy kwadratowe oznaczają część opcjonalną.

Wykonując polecenie select, pdksh generuje numerowane menu dla wszystkich elementów w liście lista_pozycji. lista_pozycji może być zmienną zawierającą więcej niż jedną pozycję menu, np. poz1 poz2, ale może być również wpisana bezpośrednio, na przykład:

select pozycjamenu in poz1 poz2 poz3

Jeśli lista_pozycji nie jest podana, polecenie select używa parametrów pozycyjnych, podobnie jak polecenie for.

Po wybraniu jednej z pozycji menu (przez wpisanie odpowiedniej liczby), polecenie select zapisuje informację o wybranym elemencie w zmiennej pozycjamenu. Polecenia zawarte w bloku do - done mogą następnie wykonać odpowiednie operacje.

Poniższy przykład ilustruje wykorzystanie polecenia select. Wyświetla on trzy pozycje menu, a po tym, jak użytkownik wybierze jedną z nich, pyta o potwierdzenie. Jeśli użytkownik odpowie coś innego, niż t lub T, menu wyświetlane jest ponownie.

select pozmenu in poz1 poz2 poz3
do
echo "Czy jesteś pewny, że chcesz wybrać $pozmenu?"
read odp
if [ $odp = "T" -o $odp = "t" ]
then

break
fi
done

W powyższym przykładzie wprowadzono kilka nowych poleceń. Polecenie read służy do pobierania informacji od użytkownika. Zapisuje to, co wpisze użytkownik, do zmiennej podanej jako jego parametr. Polecenie break służy do opuszczania pętli while, until, repeat, select lub for.

Instrukcja repeat

tcsh obsługuje instrukcję nie mającą odpowiednika ani w powłoce pdksh, ani bash. Jest to instrukcja repeat. Wykonuje ona pojedyncze polecenie zadaną ilość razy. Jej składnia jest następująca:

repeat ilość polecenie

Poniżej podano przykład wykorzystania instrukcji repeat. Pobiera on zestaw liczb z wiersza poleceń, po czym wyświetla odpowiadającą każdej liczbie ilość kropek.

#
foreach num ($*)
repeat $num echo -n "."
echo ""
end

0x01 graphic

Każda pętla repeat może być zastąpiona pętlą while lub for. Czasem jednak składnia polecenia repeat jest wygodniejsza.

Funkcje

Języki powłoki pozwalają również definiować własne funkcje. Funkcje takie zachowują się podobnie jak definiowane w języku C czy innych językach programowania. Głównym powodem ich stosowania jest lepsza organizacja kodu programów. Kod pisany z wykorzystaniem funkcji jest o wiele bardziej czytelny, często również jest krótszy, ponieważ powtarzające się instrukcje można zebrać w jednej funkcji, wywoływanej w miejscu, w której miałyby się one pojawić. Powłoka tcsh nie obsługuje funkcji.

Składnia polecenia definiującego funkcję w interpreterach bash i pdksh jest następująca:

nazwafunkcji () {
polecenia
}

pdksh obsługuje również składnię:

function nazwafunkcji {
polecenia
}

Obie formy są identyczne pod względem działania.

Po zdefiniowaniu funkcji można ją wywołać poleceniem:

nazwafunkcji [param1 param2 param3 ...]

Zauważ, że do funkcji przekazać można dowolną ilość parametrów. Wewnątrz funkcji są one widziane jako parametry pozycyjne, tak, jakby zostały wprowadzone jako argumenty wywołania. Poniższy program powłoki zawiera kilka funkcji, z których każda obsługuje jedną z opcji podawanych w wierszu poleceń. Odczytuje on wszystkie pliki, których nazwy podano w wierszu poleceń, a następnie, w zależności od podanej opcji, zamienia wszystkie litery w pliku na wielkie, małe lub też drukuje poszczególne pliki.

upper () {
shift
for i
do
tr a-z A-Z <$1 >$1.out
rm $1
mv $1.out $1
shift
done; }

lower () {
shift
for i
do
tr A-Z a-z <$1 >$1.out
rm $1
mv $1.out $1
shift
done; }
print () {
shift
for i
do
lpr $1
shift
done; }


blad () {
echo "Skladnia polecenia $1: $1 <opcja> <pliki_wejsciowe>"
echo ""
echo "opcja może przyjmowac nastepujace wartosci"
echo "p drukowanie plikow"
echo "u zamiana na wielkie litery"
echo "l zamiana na male litery"
case $1
in
p | -p) print $@;;
u |-u) upper $@;;
l |-l) lower $@;;
*) blad $0;;

esac

Podsumowanie

W tym rozdziale przedstawiliśmy wiele aspektów programowania w języku powłoki. Zaawansowani użytkownicy Linuxa używają tego języka bardzo często.

Choć języki powłoki są dość potężne i łatwe do opanowania, zdarzają się problemy, do których rozwiązywania skrypty powłoki po prostu się nie nadają. Wtedy prawdopodobnie będziesz chciał użyć jednego z innych języków programowania dostępnych dla Linuxa.

Język awk, który jest bardzo przydatny przy wyszukiwaniu tekstów pasujących do wzorców oraz przetwarzaniu dużych zbiorów danych liczbowych, omówiony jest w rozdziale 25. „gawk”.

Perl, używany głównie do pisania szybkich skryptów oraz obsługi stron WWW, jest opisany w rozdziale 28. „Perl”.

Język Smalltalk/X, w którym tworzyć można aplikacje zorientowane obiektowo działające w środowisku X Window, przedstawiony jest w rozdziale 31. „Smalltalk/X”.

272 Część II Poznawanie Linuxa

272 E:\Moje dokumenty\HELION\Linux Unleashed\Indeks\14.DOC

E:\Moje dokumenty\HELION\Linux Unleashed\Indeks\14.DOC 255

Rozdzia³ 14. Programowanie w języku powłoki 261



Wyszukiwarka

Podobne podstrony:
43, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
34, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
58, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
26, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
08, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
10, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
57, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
29, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
46, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
60, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
36, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
49, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
62, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
D, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
55, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
28, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
61, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
42, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta
03, ciekawostki, Linux - Ksiega Eksperta, Linux - ksiega eksperta, Linux - księga eksperta

więcej podobnych podstron