KOSA
Bywalec
Dołączył: 09 Gru 2007
Posty: 40
Przeczytał: 0 tematów
|
Wysłany: Nie 14:08, 15 Cze 2008 Temat postu: Materiały w formie elektronicznej - wklejam na forum :-) |
|
|
Uruchamianie skryptów
Skrypty uruchamiamy na kilka sposobów:
• poprzez wpisanie:
bash skrypt
• nadając plikowi prawo wykonywania:
chmod +x skrypt
a następnie uruchomienie:
./skrypt
• najprościej:
skrypt
Aby tak uczynić należy spełnić jeden z dwóch warunków:
Skopiować plik do katalogu ~./bin lub do /usr/bin albo zmodyfikować zmienną $PATH.
Wyświetlanie tekstu
#!/bin/bash
echo "ten tekst zostanie wyswietlony"
echo "w dwoch wierszach"
Aby oba teksty zostały wyświetlone w jednej linii trzeba dopisać parametr-n do polecenia echo. Wtedy nie jest dodawany znak nowego wiersza:
#!/bin/bash
echo -n "To jest tylko"
echo "jedna linijka tekstu"
Zeby spowodować przejście do nowego wiersza, należy użyć znaku \n oraz parametru -e dla polecenia echo .
#!/bin/bash
echo -e "To jest pierwszy wiersz \n a to drugi"
Znaki specjalne:
Przekierowania (redirekcja)
Wyniki działań większości poleceń wysyłane są bezpośrednio na ekran monitora. Jednak często zdarza się że chcielibyśmy zapisać je w postaci pliku. Tutaj z pomocą przychodzą przekierowania strumieni.
Przykładowo chcąc zapisać listę plików wyświetlaną poleceniem ls do pliku zrobilibyśmy następująco:
ls > plik
Jeśli taki plik już istniał zostanie nadpisany, czyli stara zawartość zginie i zostanie zastąpiona nową. Jeżeli nie było pliku o tej nazwie zostanie on utworzony.
Dopisanie do pliku bez usuwania starej zawartości odbywa się za pomocą dwóch strzałek:
ls >> plik
Często zdarza się że chcemy zapisać komunikaty błędów. W tym wypadku musimy odebrać dane ze strumienia błędów. Robimy to pisząc 2> jako znak przekierowania:
sl 2> plik
Ponieważ polecenia sl nie ma w systemie - do pliku zostanie zapisany komunikat błędu
Jeżeli chcemy szybko zapisać jakiś wyraz do pliku, wcale nie musimy otwierać żadnego edytora tekstu. Wystarczy zrobić przekierowanie polecenia echo:
echo "Jakiś napis" > plik
A co w przypadku gdy jednocześnie chcemy wysłać dane na ekran oraz do pliku? Tu z pomocą przychodzi nam programik o nazwie tee, który wstawiony w potok za naszym poleceniem wysyła dane jednocześnie na ekran i na twardy dysk. Robi się to następująco:
ls | tee plik
Proste prawda?
Teraz pokażę jak połączyć wiele plików w jeden za pomocą polecenia cat i oczywiście przekierowań.
Polecenie cat wyświetla zawartość pliku (lub kilku).
cat plik1 plik2 > plik3
W ten prosty sposób dane z obydwu plików znalazły się w postaci jednego dużego pliku.
Co więcej - możemy nawet dokonać podobnej czynności z wszystkimi plikami w bieżącym katalogu stosując zamiast nazwy pliku gwiazdkę:
cat * > wszystkie
Istnieje również mechanizm wczytania danych za pomocą odwrotnego przekierowania. Bliżej poznamy go w następnych rozdziałach. Teraz dam tylkko krótki przykład jak można za jego pomocą pobrać tekst z pliku i wysłać do pocztą elektroniczną:
mail [link widoczny dla zalogowanych] < plik_z_wiadomoscia
Dla uściślenia dodam jak nazywają sie kierunki strumieni danych:
stdin - wejście
stdout - wyjście podstawowe
stderr - wyjście diagnostyczne
Aliasy
Alias to po prostu druga nazwa dla danego polecenia.
Jeśli napiszemy:
alias ll="ls -l"
lub
alias ll='ls -l'
będziemy mogli używać zamiast ls -l polecenie ll , które jest znacznie krótsze.
Uwaga: alias ten zniknie po wylogowaniu!
Aby zachować alias należy go dopisać do któregoś ze skryptów startowych np.:
~/.bashrc
lub
/etc/profile
W tym przypadku alias będzie dostępny dla wszystkich użytkowników.
Można to zrobić w ten sposób:
echo "alias ll=\"ls -l\"" >> ~./bashrc
Listę dostępnych aliasów wyświetlamy poleceniem: alias .
Często używane aliasy:
alias vi='vim'
alias md='mkdir'
alias sl='ls'
Polecenie unalias usuwa alias z pamięci.
Przeszukiwanie plików
Program grep przeszukuje plik i wyświetla linie pasujące do wzorca (czyli linie które zawierają szukane słowo).
składnia:
grep szukane_slowo plik
# wiersze zawierające słowo "Linux" w pliku "konfiguracja":
grep Linux konfiguracja
# wiersze ze słowem mariusz w pliku /etc/passwd
grep mariusz /etc/passwd
# wiersze ze słowem Linux we wszystkich plikach *.txt, *.htm i *.html
grep Linux *.{txt,htm?}
Krótki skrypt proszący o nazwę szukanego słowa oraz pliku tekstowego do przeszukania:
#!/bin/bash
echo -n "Szukane slowo: "
read slowo
echo -n "Plik: "
read plik
grep "$slowo" "$plik"
Polecenie
ls | grep ja
wyświetli wszystkie pliki których nazwa zawiera łańcuch ja np. ja, janek, aleja itp.
Gdy chcemy wyświetlić liki do któryh wszyscy mają dowolny dostęp:
ls -l | grep rwxrwxrwx
Wyrażenie:
grep Anna *
Będzie szukać wyrazu Anna we wszystkich plikach bieżącego katalogu
Uzyteczne opcje:
-i - nie zwraca uwagi na wielkość liter
-l - wypisuje tylko nazwy plików
-c - wyświetla tylko numery linii
-w - wyszukuje konkretne słowo tzn. jeśli zażyczymy sobie ciąg 'ma' to zwróci tylko te wiersze w których wystąpił dwuliterowy wyraz 'ma' a nie np. 'mama'
-r - przeszukuje katalog rekursywnie tzn. zagłębia się w strukturę katalogów szukając wyrażenia również w podkatalogach
-C , -C 1, lub -1 - wypisuje określoną ilość linii (domyślnie 2) kontekstu na wyjściu
-E -interpretuje wzorzec jako rozszerzone wyrażenie regularne
-e-używa wzoraca jako wzorac (użyteczne dla ochronienia wzorów zaczynających się od -)
-v -wybiera linie nie pasujące
-x -wybiera tylko te dopasowania które pasują do całej linii
Grep a cytowanie
grep "$HOME" *
podstawia za wyrażenie wartość zmiennej oznaczającej katalog domowy a więc działa tak samo jakbyśmy napisali:
grep "/home/mariusz" *
Gdyby chodziło nam o napis $HOME należy zastosować pojedyńcze cudzysłowy:
grep '$HOME' *
Wyrażenia regularne a grep
Wyrażenia regularne ulatwiaja nam szukanie łańcuchów (wyrazów) w plikach lub w wynikach poleceń wyrzucanych przez konsolę.
Kropka . dopasowuje dowolny pojedynczy znak czyli chcemy wypisac:
- wyrazy trzyliterowe w pliku:
grep ... plik.txt
- trzyliterowe wyrazy które koncza sie końcówką la
grep .la plik.txt
- pięcioliterowe wyrazy mające na trzecim miejscu m a na pozostalych miejscach dowolne znaki
grep ..m.. plik.txt
Jeśli naprawdę chodziłoby nam o wyszukanie kropki np wiersza zawierającego nazwę obraz.gif to znak kropki trzeba "zamaskować" czyli postawić przed nim znak prawego ukośnika:
grep 'obraz\.gif' plik
Znak ^ dopasowuje występujące przed nim wyrażenie do początku wiersza.
- wyrazy rozpoczynajace sie na literę M
grep ^M plik
- wyrazy rozpoczynające się na Mar
grep ^Mar plik
wypisze: Marta Mariusz Marian martenowski
Znak $ działa dokładnie odwrotnie czyli dopasowuje wyrażenie do końca wiersza (piszemy go za wyrażeniem):
- wyrazy kończące się na -la
grep la$ plik
wypisze: ala ela ola krasnala itp.
Wyrażenie w nawiasach kwadratowych [] dopasowuje jeden dowolny znak znajdujący się między nawiasami np.:
- dopasowanie wyrazow ala ola ela
grep [alo]la plik
- dopasowanie wyrazow kot, kat
k[oa]t
Dzieki nawiasom możemy dopasowywać całe zakresy znaków. Przypuśćmy że chcielibyśmy wyświetlić wyrazy zawierające na drugim miejscu dowolną literę:
Zgodnie z tym co poznaliśmy do tej pory napisalibyśmy
a[abcdefghijklmnoprstuwxyz]la
Okazuje się że można zrobić to o wiele prościej - ciąg zawierający wszystkie wyrazy zastąpić takim: [a-z]
a[a-z]la
Oczywiście nie musimy wyszukiwać całego przedziału: można napisać po prostu [a-d]
Tutaj nadmienie jeszcze że aby wypisać również znaki zawierające wielkie litery należy napisać:
[A-Za_z]
W taki sam prosty sposób możemy postąpić z liczbami:
zamiast pisać [0123456789] wystarczy:
[0-9]
Ważna ciekawostka:
Operator [^ ] dopasowuje dowolny znak który nie znajduje się w nawiasach.
Jeżeli chcemy wypisać wszystkie znaki NIE zawierające znaku z tego przedziału dodajemy W NAWIASIE znak ^.
auto_[^4-6]
wyszuka:
auto_1 auto_2 auto_3
ale auto_4 czy auto_5 juz nie.
Wszystkie znaki które nie są cyframi:
[^0-9]
Pamiętajmy że znak ^ służy też do wyszukania wyrażeń znajdujących się na początku łańcucha znaków, jednak wtedy nie znajduje się w nawiasach.
Gwiazdka * oznacza że poprzedzający element będzie dopasowany 0 lub dowolną ilość razy:
An*a
dopasuje wyrazy Ana Anna lub Annnnnna
Jak widać gwiadka ma w wyrażeniach regularnych inne znaczenie niż przy generowaniu nazw plików.
Wyrażenie kropka gwiadka oznacza dowolny ciąg znaków:
.*
dopasuje dowolną ilość znaków obojętnie jakich np wyrażenie:
.*r
dopasuje zarówno wyraz monitor jak i komputer
Nawiasy zwykłe określają zgrupowany ciąg znaków który staje się wyrażeniem regularnym. Chodzi o to że gdy napiszemy wyrażenie:
auta*
to może ono oznaczać auta autaaa itp. a gdy dodamy nawiasy:
(aut)*
to teraz zamiasy gwiazdki pojawi się już nie jedna litera tylko całe wyrażenie z nawiasu np.:
autaut autautaut itp.
Plus (+) znacza że poprzedzający element będzie dopasowany jeden lub więcej razy.
{n} Poprzedzający element pasuje dokładnie n razy.
{n,} Poprzedzający element pasuje n lub więcej razy.
{,m} Poprzedzający element jest opcjonalny i pasuje co najwyżej m razy.
{n,m} Poprzedzający element pasuje co najmniej n razy, ale nie więcej niż m razy.
Znak zapytania (?) oznacza że poprzedzający element jest opcjonalny i występuje najwyżej raz.
grep 'stacja/?' plik
dopasuje wyrazy stacj stacja ale juz np. stacjaa nie da rady.
grep 'Jan/(ek/)/?' plik
dopasuje Jan lub Janek.
Przy wybieraniu wierszy można używać kilku wyrażeń z których musi być spełnione chociaż jedno żeby zwróciło wyniki. Używamy do tego operatora OR (LUB)
grep -E "^c|^d" /etc/termcap
Wybierze wiersze zaczynające się znakiem c lub d.
Polecenie
grep "^c\|^d" /etc/termcap
da dokładnie ten sam wynik jednak znak OR czyli | trzeba zamaskować lewym ukośnikiem.
Maskowanie znaków
Przy używaniu grepa trzeba maskować następujące znaki: + | { } ( ) ?
Nie musimy tego robić gdy użyjemy opcji -E.
Zmienne
Zmienna przechowuje jakąś wartość. Odwołujemy się do niej (odczytujemy ją) pisząc znak $ bezpośrednio przed nazwą zmiennej.
#!/bin/bash
zdanie="Witaj swiecie !!!"
echo $zdanie
Wartości zmiennych można pobrać bezpośrednio od użytkownika:
#!/bin/bash
echo -n "Podaj imię: "
read imie
echo -n "Wiek: "
read wiek
echo "Twoje imię $imie i masz $wiek lat"
echo "Za 5 lat będziesz mieć $[ wiek+5 ] lat"
W ostatnim wierszu można zaobserwować dodawanie liczby 5 do wartości zmiennej. Inne przykłady działań na liczbach przedstawiam poniżej.
a=1
a=$[a+1] # 2
a=$((a+1)) # 2
let "a=a+1" # 2
let "a+=1" # 2
a=`expr $a + 1`
Najprostszy kalkulator
#!/bin/bash
echo
echo -n "Podaj dwie liczby oddzielone spacją: "
read a b
dodawanie=$[ a+b ]
odejmowanie=$[ a-b ]
mnozenie=$[ a*b ]
dzielenie_calkowite=$[ a/b ]
echo "Podane liczby: $a, $b"
echo
echo "Wynik dodawania: $dodawanie"
echo "Wynik odejmowania: $odejmowanie"
echo "Wynik mnozenia: $mnozenie"
echo "Wynik dzielenia calkowitego: $dzielenie_calkowite"
Zapis: dodawanie=$a+$b nie zadziała prawidłowo, tzn nie doda wartości zmiennych i tym samym nie przypisze wyniku zmienej $dodawanie.
Teraz pokażę że zapisy: echo $zmienna i echo "$zmienna" mogą dawać różne rezultaty:
#!/bin/bash
napis="Pisanie skryptow nie jest trudne"
echo $napis # Pisanie skryptow nie jest trudne
echo "$napis" # Pisanie skryptow nie jest trudne
Zapis zmiennej tekstowej bez cudzysłowu usuwa nadwymiarowe odstępy.
Aby zmienna była widoczna w innych powłokach należy ją wyeksportować:
export zdanie
Usuwanie zmiennej z pamieci:
unset zdanie
Zmienne systemowe
W Linuksie istnieje wiele wbudowanych zmiennych. Aktualną ich liste wyświetlamy poleceniami set oraz printenv. Można ich używać następująco:
#!/bin/bash
echo "Witaj $USER, Twoj katalog domowy to $HOME, nazwa i typ tego komputera to $HOSTNAME $HOSTTYPE, znajdujesz sie w katalogu $PWD"
Przykładowe wyniki mogą być następujące
Witaj mariusz, Twoj katalog domowy to /home/mariusz, nazwa i typ tego komputera to unix i386, znajdujesz sie w katalogu /tmp.
Warunki
W języku Shell, tak jak i w wielu innych językach programowania, stosuje się tzw. wyrażenia warunkowe które pozwalaja sterowac działaniem programu.
test
Najkrócej warunek można zapisać w ten sposób
[ $a -eq $b ] && echo "a jest równe b" || echo "Zmienne się różnią"
Czyli: jeśli $a jest równe $b wyświetl komunikat "a jest równe b", w przeciwnym wypadku wyświetl zdanie "Zmienne się różnią".
Wyrażenie w nawiasach kwadratowych jest to warunek testujący używający programu test. Test zwraca kod zakończenia równy 0 gdy warunek został spełniony, w innym przypadku kod zakończenia wynosi 1. Lista dostępnych warunków znajduje się na dole strony oraz w man test.
if-then-fi
if warunek_jest_spelniony
then
polecenie
fi
Wyrażenie to czytamy następująco: Jeżeli warunek jest spełniony wykonaj polecenie.
Skrypt sprawdza czy istnieje plik o nazwie moj_plik
oraz informuje nas, jesli jest to prawdą
#!/bin/bash
if [ -e moj_plik ]
then
echo "Masz plik moj_plik"
fi
Bardzo ważne: nawiasy muszą być odzielone spacją, inaczej nie będzie działać.
-e oznacza - wyrażenie jest prawdziwe, gdy plik o nazwie moj_plik istnieje (exist)
Gdybyśmy chcieli sprawdzić istnienie pliku w swoim katalogu domowym, napisalibyśmy:
if [ -e ~/moj_plik ]
if-then-else-fi
Wyrażenie czytamy następująco: Jeżeli warunek jest spełniony wykonaj polecenie1, jeśli nie jest - wykonaj polecenie2.
if warunek_spelniony
then
polecenie1
else
polecenie2
fi
Skrypt sprawdza czy istnieje plik o nazwie moj_plik
oraz generuje odpowiedni komunikat
#!/bin/bash
if [ -e moj_plik ]
then
echo "Masz plik moj_plik"
else
echo "Nie masz pliku moj_plik"
fi
if-then-elif-else-fi
Tego wyrażenia używamy gdy potrzeba sprawdzić kilka warunków, jednak chodzi nam tylko o spełnienie tylko jednego z nich.
Wyrażenie sprawdza po kolei, który warunek jest spełniony, jeśli taki znajdzie wykona polecenie mu przyporządkowane. Jeśli nie będzie spełniony żaden z warunków, wykonane zostanie polecenie widoczne po instrukcji else.
if warunek1
then
polecenie1
elif warunek2
polecenie2
elif warunek3
polecenie3
else
polecenie4
fi
Uwaga: jeśli dodamy znaku wykrzyknika przed warunkiem, to polecenie wykona się tylko wtedy, gdy warunek NIE jest spełniony, np instrukcja
if [ ! -e plik ]
then
polecenie
fi
spowoduje że polecenie wykona się tylko wtedy, gdy plik NIE istnieje.
Skrypt sprawdza czy plik o nazwie moj_plik jest zwykłym plikiem,
katalogiem, czy dowiązaniem symbolicznym
#!/bin/bash
if [ ! -e moj_plik ] ;then
echo "Plik nie istnieje"
elif [ -f moj_plik ] ;then
echo "Zwykły plik"
elif [ -d moj_plik ];then
echo "Katalog"
elif [ -L moj_plik ];then
echo "Dowiazanie symboliczne"
else
echo "Nie moge dopasowac rodzaju pliku"
fi
Skrypt pyta o hasło i sprawdza czy jest poprawne
#!/bin/bash
echo "Podaj haslo"
read haslo
if [ "$haslo" = "tajne" ]
then
echo "Prawidlowe haslo"
else
echo "Dostep zabroniony"
fi
Skrypt pyta o hasło i sprawdza czy jest poprawne
wersja z niewidocznym hasłem
#!/bin/bash
printf "Podaj haslo: "
stty -echo
read haslo
stty echo
if [ "$haslo" = "tajne" ]
then
echo "Prawidlowe haslo"
else
echo "Dostep zabroniony"
fi
Lista ważniejszych warunków:
-e plik - prawda, jeśli plik istnieje
-d plik - prawda, jeśli plik istnieje i jest katalogiem
-f plik - prawda, jeśli plik istnieje i jest zwykłym plikiem
-L plik - prawda, jeśli plik istnieje i jest dowiązaniem symbolicznym
-r plik - prawda, jeśli plik istnieje i można go czytać
-w plik - prawda, jeśli plik istnieje i można do niego pisać
-x plik - prawda, jeśli plik istnieje i można go wykonywać
-s plik - prawda, jeśli plik istnieje i ma rozmiar większy od zera
-g plik - prawda, jeśli plik istnieje i ma ustawiony bit set-group-id
-u plik - prawda, jeśli plik istnieje i ma ustawiony bit set-user-id
-b plik - prawda, jeśli plik istnieje i jest urządzeniem blokowym
-c plik - prawda, jeśli plik istnieje i jest urządzeniem znakowym
plik1 -nt plik2 - prawda, jeśli plik1 jest nowszy (zgodnie z datą modyfikacji) niż plik2
plik1 -ot plik2 - prawda, jeśli plik1 jest starszy niż plik2
plik1 -ef plik2 - prawda, jeśli plik1 i plik2 mają te same numery urządzenia i i-węzła
-z ciąg - prawda, jeśli ciąg długość równą zero
-n ciąg - prawda, jeśli ciąg długość większą od zera
ciąg1 = ciąg2 - prawda, jeżeli ciągi są jednakowe
ciąg1 != ciąg2 - prawda, jeżeli ciągi są różne
! wyrażenie - prawda, jeżeli wyrażenie jest fałszywe
wyrażenie -a wyrażenie -prawda, jeśli oba wyrażenia są prawdziwe
wyrażenie -o wyrażenie - prawda, jeżeli przynajmniej jedno z wyrażeń jest prawdziwe
argument1 -eq argument2 - prawda, jeśli argument1 jest równy argumentowi2
argument1 -ne argument2 - prawda, jeśli argument1 jest różny od argumentu2
argument1 -gt argument2 - prawda, jeśli argument1 jest większy od argumentu2
argument1 -ge argument2 - prawda, jeśli argument1 jest większy lub równy argumentu2
argument1 -lt argument2 - prawda, jeśli argument1 jest mniejszy od argumentu2
argument1 -le argument2 - prawda, jeśli argument1 jest mniejszy lub równy argumentowi2
Instrukcja wyboru Case
Składnia case wygląda następująco
case $nazwa_zmiennej in
"wzorzec1") polecenie1 ;;
"wzorzec2") polecenie2 ;;
.
.
.
*)polecenie
esac
Prosty przykład menu zbudowanego za pomocą case:
#!/bin/bash
echo "Wybierz opcje"
echo "1) Opcja-1"
echo "2) Opcja-2"
echo "3) Opcja-3"
read wybor
case $wybor in
1) echo "Wybrales 1";;
2) echo "Wybrales 2";;
3) echo "Wybrales 3";;
*) echo "Wybrales nieznana opcje" ;;
esac
Skrypt pyta o hasło i sprawdza czy jest poprawne
wersja z uzyciem petli while i instrukcji case
#!/bin/bash
while [ 1 ]
do
echo "Podaj haslo dostepu, q - wychodzi ze skryptu"
echo -n "Haslo: "
read haslo
case $haslo in
"admin") echo "Hasło poprawne, witaj adminie" ; break ;;
"student") echo "Hasło poprawne, witaj studencie" ; break ;;
"q") echo "Wyjscie" ; exit ;;
*)continue ;;
esac
done
Dzięki użyciu instrukcji case kod jest bardziej przejrzysty, poza tym teraz łatwo można przyporządkować każdej osobie opowiednie polecenia (oddzielamy je średnikami).
Skrypt pokazujący dialog z użytkownikiem:
#!/bin/bash
powitanie="Dzien dobry"
pan="Panu"
pani="Pani"
echo "Czy jestes mezczyzna? (T/N)"
read plec
case $plec in
t) echo "$powitanie $pan";;
T) echo "$powitanie $pan";;
n) echo "$powitanie $pani";;
N) echo "$powitanie $pani";;
*) echo "Niezrozumiala odpowiedz" ;;
esac
Taki sam skrypt napisany z użyciem warunków:
#!/bin/bash
powitanie="Dzien dobry"
pan="Panu"
pani="Pani"
echo "Czy jestes mezczyzna? (T/N)"
read plec
if [ "$plec" = "t" ] || [ "$plec" = "T" ]
then
echo "$powitanie $pan"
elif [ "$plec" = "n" ] || [ "$plec" = "N" ]
then
echo "$powitanie $pani"
else
echo "Niezrozumiala odpowiedz"
fi
Instrukcja wyboru select-case
Jest bardzo podobna do instrukcji Case. Dzięki niej łatwo zbudować menu (nie potrzeba stosować echo do wyświetlania opcji)
Składnia:
select nr in 1 2 3
do
case $nr in
"1") Polecenie1
"2") Polecenie2
"3") Polecenie3
"*") Polecenie
esac
break
done
Poniżej skrypt pokazujący jak można zbudować menu za pomocą instrukcji wyboru select-case
Skrypt WYBIERZ EDYTOR
wersja korzystająca z instrukcji select case
#!/bin/bash
select nr in vi mcedit pico wyjscie
do
case $nr in
"vi") vi ; break ;;
"mcedit") mcedit ; break ;;
"pico") pico ; break ;;
"wyjscie") echo "wyjscie" ; exit ;;
*) continue ;;
esac
break
done
Pętle
Pętla wykonuje jakieś działanie wiele razy. Może to być wyświetlanie, zliczanie bądź numeracja wielu plików, pytanie o hasło dopóki użytkownik nie poda właściwego czy dodawanie do siebie wielu kolejnych liczb.
While
Pętla while wykonuje działanie tylko wtedy gdy warunek jest spełniony.
Składnia:
while warunek_jest_prawdziwy
do
instrukcje
done
czyli:
dopóki warunek_jest_prawdziwy
wykonuj
instrukcje
zakończ
Poniżej przedstawiam prosty skrypt wyświetlający liczby do 1 do 10.
#!/bin/bash
a=1
while [ $a -le 10 ] # dopoki $a <= 10
do
echo "Biezaca liczba: $a" # wyswietlenie biezacej zmiennej
a=$[a+1] # zwiekszenie licznika o 1
done
Instrukcje break i continue służą do sterowania przebiegiem pętli.
- break - powoduje natychmiastowe wyjście poza pętlę
- continue - powoduje natychmiastowe wykonanie następnego przejścia pętli, bez wykonywania dalszych instrukcji
Instrukcja exit powoduje natychmiastowe wyjście ze skryptu.
Pętla nieskończona.
Jeśli napiszemy:
while [ 1 ]
do
instrukcje
done
to pętla ta będzie wykonywać się bez końca. Jednak dzięki wstawieniu instrukcji break możemy bez żadnego problemu wyjśc z pętli kiedy jest to potrzebne np:
while [ 1 ]
do
echo "Wpisz koniec aby zakonczyc"
read kod
if [ "$kod" = "koniec" ]
then
break
fi
done
echo "Jestem poza petla !"
Jeśli w przypadku wpisania "wyjscie" chcielibyśmy opuścić całkowicie skrypt - używamy instrukcji exit:
while [ 1 ]
do
echo "Wpisz koniec aby zakonczyc"
read kod
if [ "$kod" = "koniec" ]
then
exit
fi
done
echo "To sie nigdy nie wyswietli"
Jeśli chcemy aby po wpisaniu nieprawidłowego hasła komputer zapytał nas o to jeszcze raz (a nawet więcej) to najwygodniej użyć pętli:
Skrypt pyta o hasło i sprawdza czy jest poprawne
wersja z uzyciem petli while
Aby wyjsc nie podajac hasla trzeba nacisnac klawisze CTRL+C
#!/bin/bash
while [ 1 ]
do
echo -n "Podaj haslo: "
read haslo
if [ "$haslo" = "tajne" ]
then
echo "Prawidlowe haslo"
break # wyjscie z petli
else
echo "Dostep zabroniony"
continue # kolejne przejscie petli
fi
done
Jeśli mamy więcej pasujących haseł zamiast:
if [ "$haslo" = "tajne" ]
możemy napisać następująco:
if [ "$haslo" = "tajne" ] || [ "$haslo" = "inne" ]
Znak: || oznacza tzw. sumę logiczną czyli "lub"
Elegancko byłoby dodać opcję wyjścia gdy nie znamy hasła
Użyjemy do tego instrukcji case, służącej do porównywania ze wzorcem
Skrypt MENU
wersja korzystająca z instrukcji case
oraz działająca w pętli while
#!/bin/bash
while [ 1 ]
do
clear # Czysci ekran
echo "Wybierz edytor który chcesz uruchomić"
echo "1 - vi"
echo "2 - mcedit"
echo "3 - pico"
echo "4 - wyjscie"
read nr
case $nr in
"1") vi ; break ;;
"2") mcedit ; break ;;
"3") pico ; break ;;
"4") echo "Wyjscie" ; exit ;;
*) continue ;;
esac
done
Skrypt WYBIERZ EDYTOR
wersja korzystająca z instrukcji select case
oraz działająca w pętli while
#!/bin/bash
while [ 1 ]
do
select nr in vi mcedit pico wyjscie
do
case $nr in
"vi") vi ; break ;;
"mcedit") mcedit ; break ;;
"pico") pico ; break ;;
"wyjscie") echo "wyjscie" ; exit ;;
*) continue ;;
esac
break
done
done
Pętla Until
Pętla until jest odwrotością pętli while. Wykonuje się dopóki warunek jest fałszywy.
Składnia:
while warunek_jest_prawdziwy
do
instrukcje
done
czyli:
dopóki warunek_jest_prawdziwy
wykonuj
instrukcje
zakończ
Poniżej przedstawiam prosty skrypt wyświetlający liczby do 1 do 10.
#!/bin/bash
a=1
until [ $a -ge 10 ] # dopoki $a >= 10
do
echo "Biezaca liczba: $a" # wyswietlenie biezacej zmiennej
a=$[a+1] # zwiekszenie licznika o 1
done
Pętla for
Pętla for wykonuje to samo działanie dla wielu liczb, wyrazów, plików itp.
Istnieją dwie wersje pętli for. Pierwsza jest bardzo podobna do tej spotykanej w innych językach programowania:
Składnia:
for (( zmienna = 0 ; zmienna <= 5; zmienna++ )) # Wykonuj petle liczac od 0 do 5
do # wykonaj
... # jakieś instrukcje
done # koniec pętli
Przykład:
#!/bin/bash
for (( i = 0 ; i <= 5; i++ ))
do
echo "Witam $i raz"
done
wyświetli:
Witam 0 raz
Witam 1 raz
Witam 2 raz
Witam 3 raz
Witam 4 raz
Witam 5 raz
Druga wersja jest szczególnie ukierunkowana na działania na plikach.
Składnia:
for zmienna in lista # dla każdej wartości znajdującej się na liście
do # wykonaj
... # jakieś instrukcje
done # koniec pętli
Wyświetlenie liczb 1-5:
#!/bin/bash
for nr in 1 2 3 4 5
do
echo $nr # wyświetl bieżącą zmienną
done
echo "Petla zakonczona"
Jeśli chcielibyśmu odzielić liczby wynikowe spacjami (a nie znakami nowego wiersza), możemy to zrobić dopisując parametr -n do polecenia echo:
#!/bin/bash
for motor in 1 2 3 4 5
do
echo -n $nr
echo -n " "
done
echo # wyswietlenie znaku nowego wiersza
Zmienne na liście mogą być też łańcuchami:
Wyświetlenie marek motocykli
#!/bin/bash
for motor in Honda Yamaha Suzuki Kawasaki Harley
do
echo $motor # wyświetl bieżącą zmienną
done
Jeśli chcielibyśmy odzielić spacją wyniki, można to zrobić następująco
Wyświetlenie plików znajdujących się w bieżącym katalogu przy pomocy pętli for
#!/bin/bash
for plik in * # gwiazdka oznacza wszystkie pliki w bieżącym katalogu
# mozna zapisać dowolną inną ścieżkę
do
echo $plik
done
Wyświetlenie plików znajdujących się w /etc/* przy pomocy pętli for
#!/bin/bash
for plik in /etc/*
do
echo $plik
done
Skrypt zmienia prawa dostępu plikow z rozszerzeniem *.exe znajdujących się w bieżącym katalogu przy pomocy pętli for
#!/bin/bash
for plik in *.exe
do
echo -e "Zmieniam prawa dostępu do pliku\t $plik"
chmod 755 $plik
done
Za pomocą pętli for możemy dokonać dowolnej operacji na każdym z plików:
Skrypt łączący w jedną całość pliki *.txt w bieżącym katalogu
#!/bin/bash
for plik in `ls *.txt` # lub $(ls *.txt)
do
cat $plik >> calosc.txt
done
Wyświetlenie plików z podaniem kryteriów wyszukiwania przy pomocy pętli for
#!/bin/bash
echo "Podaj sciezkę dostępu do katalogu(np. /etc)"
read sciezka
echo "Kryteria wyswietlania(np. *, [ao]la itp.)"
read kryteria
for plik in $sciezka/$kryteria
do
echo $plik
liczba_plikow=$[ liczba_plikow+ 1] # zliczanie wyświetlonych plików
done
echo
echo "Liczba wyświetlonych plików: $liczba_plikow"
Skrypt łączący w jedną całość pliki *.txt w bieżącym katalogu
wersja rozszerzona
#!/bin/bash
# jesli istnieje plik calosc.txt zapytaj co robic
if [ -f calosc.txt ]; then
echo "Plik calosc.txt juz istnieje. Usunac jego zawartosc? (T/N)"
while [ 1 ]
do
read usun
if [ "$usun" = "T" ] || [ "$usun" = "t" ] ;then
rm calosc.txt
break
elif [ "$usun" = "N" ] || [ "$usun" = "n" ] ;then
break # przejdz dalej (czyli dopisze do pliku)
else
echo "Nieprawidlowy wybor. Wcisnij T lub N."
continue # wybierz ponownie
fi
done
fi
ilosc=0
for plik in `ls *.txt` # lub $(ls *.txt)
do
# jesli wlasnie przetawarzany plik to plik wynikowy
# bo tez ma rozszerzenie *.txt a wiec program bierze go pod uwage,
# opusc go (przejdz do nastepnego pliku w petli)
# inaczej dodalby zawartosc pliku wynikowego do jego samego
if [ "$plik" = "calosc.txt" ];then continue; fi
echo -e "\nNazwa pliku: $plik" >> calosc.txt # dodanie nazwy pliku
echo -e "----zawartosc-------\n" >> calosc.txt
cat $plik >> calosc.txt
let ilosc=ilosc+1 # licznik plikow
done
echo -e "\nDodano zawartosc $ilosc plikow\n"
echo -n "Wyswietlic wynikowy plik? (T) "
read pokaz
if [ "$pokaz" = "T" ] || [ "$pokaz" = "t" ]
then
echo -e "\nZawartosc pliku calosc.txt:\n"
cat calosc.txt
fi
Funkcje
Funkcje są bardzo przydatne ponieważ pozwalają nam na wielokrotne używanie kodu oraz dzielenie go na mniejsze części - odpowiadające tylko za jedną rzecz np. wysyłanie e-maila.
Przykład skryptu z funkcjami:
#!/bin/bash
# deklaracja funkcji
function powitanie
{
echo "Witaj !"
}
# wywołanie funkcji
powitanie
Po uruchomieniu skryptu zobaczymy napis "Witaj !".
Funkcję możemy wywołać dowolną ilość razy
#!/bin/bash
function powitanie
{
echo "Witaj !"
}
powitanie
powitanie
oraz z dowolnej instrukcji/pętli
#!/bin/bash
function wyswietl
{
ls -l
}
function zakonczenie
{ exit
}
echo "Co chcesz wykonać?"
select opcja in WYSWIETLIC_PLIKI ZAKONCZYC
do
case $opcja in WYSWIETLIC_PLIKI) wyswietl ;;
ZAKONCZYC) zakonczenie;;
esac
break
done
Programujący wcześniej w innych językach pewnie zastanawiają się czy można przekazać parametry do funkcji. Oczywiście że tak. Robi się to następująco:
#!/bin/bash
function param
{
echo -n "Oto pierwszy parametr: "
echo $1
echo -n "A to drugi: "
echo $2
}
param dlugosc 23
Funkcja może również zwracać wartość a więc przekazywać nam wynik obliczeń lub informować czy polecenia przez nią wykonywane zostały zakończone poprawnie. Używamy do tego instrukcji return. Zwrócona wartość znajduje się w zmiennej $?.
dodaj()
{
wynik=`expr $1 + $2`
return $wynik
}
dodaj 1 2
echo "Wynikiem dodawania jest $?"
Ostatnio zmieniony przez KOSA dnia Nie 14:22, 15 Cze 2008, w całości zmieniany 1 raz
|
|