|
|
|
|
Ostatnie zmiany
08.12.2000
|
|
|
Programing - Linux Shell Script Tutorial
Wprowadzenie do programowania w powłoce
Program w powłoce jest ciągiem poleceń Linuksa. Skrypt powłoki (shella) jest
czymś w rodzaju plików *.bat w MS-DOS ale ma znacznie więcej możliwości niż w
MS-DOS plik *.bat. Skrypt powłoki może pobrać dane od użytkownika lub z pliku
a rezultat wyświetlić na ekranie. Skrypty są przydatne do tworzenia naszych
własnych poleceń, które mogą oszczędzić nam dużo czasu i zautomatyzować część
działań które przeprowadzamy w ciągu dnia.
Zmienne w Linuksie
Aby komputer mógł przetworzyć nasze dane/informacje, muszą być one
przechowane w pamięci RAM komputera. Pamięć RAM jest podzielona na małe
jednostki, i każda jednostka posiada unikalny numer zwany lokacją/adresem
pamięci, który jest używany do zachowania naszej zmiennej. Programista może
przyznać unikalną nazwę dla tego adresu pamięci, nazwę tą nazywamy zmienną
(Zmienna może przybierać różną wartość ale tylko jedna w tym samym czasie).
W Linuksie występują dwa rodzaje zmiennych
1) Zmienne systemowe - tworzone i zarządzane przez system. Ten typ
zmiennych definiowany jest DUŻYMI LITERAMI.
2) Zmienne definiowane przez użytkownika (UDV) - Tworzone i
zarządzane przez użytkownika. Ten typ zmiennych definiowany jest małymi
literami.
Wybrane zmienne systemowe
Możesz zobaczyć zmienne systemowe przez wydanie komendy $ set,
Niektóre ważne zmienne systemowe to
| Zmienna systemowa |
Znaczenie |
| BASH=/bin/bash |
Nazwa naszej powłoki |
| BASH_VERSION=1.14.7(1) |
Wersja naszej powłoki |
| COLUMNS=80 |
Liczba kolumn znaków na naszym ekranie |
| HOME=/home/vivek |
Nasz katalog domowy |
| LINES=25 |
Liczba linii na ekranie |
| LOGNAME=students |
Nasza nazwa logowania |
| OSTYPE=Linux |
Nasz typ systemu : -) |
| PATH=/usr/bin:/sbin:/bin:/usr/sbin |
Ustawienie ścieżek |
| PS1=[\u@\h \W]\$ |
Ustawienie znaku zachęty |
| PWD=/home/students/Common |
Nasz aktualnu katalog roboczy |
| SHELL=/bin/bash |
Nazwa naszej powłoki |
| USERNAME=vivek |
Nazwa użytkownika który jest aktualnie zalogowany
w tym systemie |
Uwaga: Niektóre z powyższych zmiennych mogą mieć inne ustawienia w twoim
systemie. Możesz wyświetlić każda z powyższych zmiennych podając komendę :
$ echo $USERNAME
$ echo $HOME
Uwaga: Nie modyfikuj zmiennych
systemowych gdyż to może spowodować kłopoty.
Jak zdefiniować zmienne użytkownika
(UDV)
Aby zdefiniować UDV użyj następującej składni
Składnia: nazwa_zmiennej=wartość
NOTE: Tutaj 'wartość' jest przyporządkowana do podanej 'nazwy_zmiennej' a
'wartość' musi być po prawej stronie znaku =. Na przykład:
$ no=10 # to jest dobrze
$ 10=no # Błąd, Wartość musi być po prawej
stronie znaku =.
Aby zdefiniować zmienną nazwaną 'vech' mającą wartość Bus:
$ vech=Bus
Aby zdefiniować zmienną nazwaną n mającą wartość 10 :
$ n=10
Reguły dla wyznaczania zmiennych (Dla UDV
i Zmiennych systemowych)
(1) Nazwa zmiennych musi zaczynać się od liter lub znaku podkreślenia (_) i
składać się z jednej lub więcej liter. Na przykład kilka prawidłowych nazw
zmiennych :
HOME
SYSTEM_VERSION
vech
no
(2) Nie umieszczaj spacji po obu stronach znaku równości kiedy
przyporządkowujesz wartość zmiennej .
Na przykład. W poniżej zadeklarowanej zmiennej nie ma błędu
$ no=10
Ale tutaj mogą wystąpić problemy
$ no =10
$ no= 10
$ no = 10
(3) Zmienne rozróżniają wielkości liter, tak jak pliki w Linuksie. Na
przykład :
$ no=10
$ No=11
$ NO=20
$ nO=2
Powyżej wszystkie nazwy zmiennych są dla systemu różne, więc aby wyświetlić 20
musimy użyć polecenia $ echo $NO a nie żadnego z poniższych
$ echo $no # wyświetli 10 a
nie 20
$ echo $No # wyświetli 11 a
nie 20
$ echo $nO # wyświetli 2 a
nie 20
(4) Możesz zdefiniować puste (NULL) zmienne w następujący sposób (zmienna
NULL jest zmienna która nie posiada wartości w czasie definicji) :
$ vech=
$ vech=""
spróbuj wyświetlić tą wartość $ echo $vech , tutaj nic nie zobaczymy
ponieważ zmienna nie ma wartości to znaczy ma wartość NULL.
(5) Nie używaj znaków ?,* itd. do nazywania zmiennych.
Jak wyświetlić i obsłużyć zmienne UDV (User
defined variables)
Aby wyświetlić lub dostać się do zmiennej UDV użyj następującej składni :
Składnia: $nazwazmiennej
Na przykład aby wyświetlić zawartość zmiennej 'vech'
$ echo $vech
to wyświetli wartość 'Bus' (jeżeli wcześniej zdefiniowana została jako
vech=Bus) ,aby wydrukować zawartość zmiennej 'n'
$ echo $n
Wyświetli '10' (jeżeli wcześniej zdefiniowaliśmy jako n=10)
Uwaga: Składnia $ echo vech
wyświetli vech zamiast wartości 'Bus', a $ echo n, wyświetli n zamiast
wartości '10', Musisz użyć znaku $ poprzedzającego nazwę zmiennej.
Q.1.Jak zdefiniować zmienną x o wartości 10 i wyświetlić to na ekranie
$ x=10
$ echo $x
Q.2.Jak zdefiniować zmienną xn o wartości Rani i wyświetlić to na ekranie
$ xn=Rani
$ echo $xn
Q.3.Jak wyświetlić sumę dwóch liczb, niech to będzie 6 i 3
$ echo 6 + 3
To wyświetli 6 + 3, nie sumę 9, Aby zsumować lub wykonać inna operację
matematyczną w powłoce użyj expr, składnia jest następująca
Składnia: expr op1 operator op2
Gdzie, op1 i op2 są jakąś liczbą całkowitą (liczba bez przecinka) a operatorem
może być
+ dodawanie
- odejmowanie
/ dzielenie
% reszta z dzielenia, na przykład 20 / 3 = 6 , aby znaleźć resztę 20 % 3 = 2,
(Pamiętaj że to są operacje na liczbach całkowitych)
\* mnożenie
$ expr 6 + 3 Teraz to wydrukuje sumę 9 , ale
$ expr 6+3 nie będzie działało ponieważ są wymagane spacje
pomiędzy liczbami a operatorem (Zobacz Operacje arytmetyczne w powłoce)
Q.4.Jak zdefiniować dwie wartości x=20, y=5 i wyświetlić ich dzielenie x
przez y (np. x/y)
$x=20
$ y=5
$ expr x / y
Q.5.Modyfikujemy powyższy przykład i zapisujemy wartość dzielenia x przez
y w zmiennej nazwanej z
$ x=20
$ y=5
$ z=`expr x / y`
$ echo $z
Uwaga : Aby zrozumieć trzecie wyrażenie, przeczytaj - Operacje
arytmetyczne w powłoce.
Jak napisać skrypt w powłoce
Teraz napiszemy nasz pierwszy skrypt który wyświetli "Wiedza jest Potęgą" na
ekranie. Aby napisać skrypt powłoki możesz użyć dowolnego edytora tekstowego
dostępnego w Linuksie, na przykład vi czy mcedit lub też możesz użyć polecenia
cat. Tutaj użyjemy polecenia cat jednak jeżeli wolisz możesz użyć edytora
tekstu o którym wspominałem wyżej.
Najpierw wydaj polecenie cat i wprowadź resztę tekstu jak tutaj
$ cat > first
#
# Moj pierwszy shell skrypt
#
clear
echo "Wiedza jest Potęgą"
Naciśnij Ctrl + D aby zapisać. Teraz nasz skrypt jest gotowy. Aby go wykonać
wydaj polecenie
$ ./first
Zostanie zwrócony błąd oznaczający że nie mamy ustawnego prawa wykonania
(Execute) dla naszego pierwszego skryptu; aby to zrobić (ustawić prawo
wykonania) wykonaj polecenie
$ chmod +x first
$ ./first
Najpierw ekran zostanie wyczyszczony, potem napis Wiedza jest Potęgą zostanie
wyświetlony na ekranie. Do wyświetlenia informacji o zawartości zmiennych
wykorzystaliśmy komendę echo, ogólna postać instrukcji echo jest następująca
echo "Informacja"
echo "Informacja zmienna1, zmienna2....zmiennaN"
Jak uruchomić skrypt powłoki
Ponieważ system zabezpieczenie w Linuksie, dla tworzonego skryptu powłoki
(pliku) nie daje domyślnie praw wykonania, więc jeżeli chcemy uruchomić skrypt
musimy wykonać dwie czynności
(1) Użyć komendy chmod aby przyznać prawo wykonania dla naszego skryptu
Składnia: chmod +x
nazwa-skryptu-shella
LUB
Składnia: chmod 777
nazwa-skryptu-shella
(2) Uruchomić nasz skrypt jako
Składnia: ./nazwa-skryptu-shella
Na przykład
$ ./first
Tutaj '.'(kropka) jest poleceniem i jest użyta w połączeniu ze skryptem.
Kropka(.) wskazuje dla aktualnej powłoki (shella) że instrukcja następująca po
kropce(.) powinna być wykonana w tej samej powłoce to znaczy bez ładownia
innej powłoki do pamięci. Możesz też spróbować uruchomić skrypt w następujący
sposób
Składnia: bash twój-skrypt
Lub
/bin/sh twój-skrypt
Na przykład
$ bash first
$ /bin/sh first
Uwaga: Aby tak uruchomić skrypt, musisz być w tym samym katalogu gdzie go
stworzyłeś, jeżeli jesteś w innym katalogu skrypt nie zostanie wykonany (bo
nie zostanie znaleziony na ścieżce (path)), Na przykład Twój domowy katalog to
( użyj $ pwd aby zobaczyć swój domowy katalog) /home/vivek.
Kiedy tworzysz skrypt nazwany np . 'first' a po stworzeniu tego skryptu
przenosisz się do innego katalogu, powiedzmy że /home/vivek/Letters/Personal,
potem próbujesz wykonać swój skrypt, on nie zostanie uruchomiony. Powodem tego
jest to że skrypt 'first' znajduje się w katalogu /home/vivek directory. Są
dwie drogi rozwiązania tego problemu - Pierwsza, podaj kompletną ścieżkę do
twojego skryptu jeżeli chcesz go uruchomić z innego katalogu wykonując na
przykład polecenie
$ /bin/sh /home/vivek/first
Za każdym razem, kiedy pracujesz w innym katalogu niż tym w którym
znajduje się skrypt musisz pamiętać o wszystkich szczegółach związanych z
uruchomieniem i kompletnej ścieżce do skryptu. Ale jest inna droga, zauważ że
wszystkie programy systemowe są oznaczone jako wykonywalne i mogą być wykonane
bezpośrednio z dowolnego katalogu (Aby zobaczyć takie programy wydaj na
przykład polecenie $ ls -l /bin lub ls -l /usr/bin) przez napisanie
powiedzmy
$ bc
$ cc myprg.c
$ cal
itd. Dlaczego tak jest ? Wszystkie programy systemowe są zainstalowane w
katalogu /bin a katalog /bin jest ustawiony w naszej zmiennej systemowej PATH,
kiedy wpiszesz nazwę polecenia po znaku zachęty $, powłoka najpierw sprawdzi
czy instrukcja nie należy do części wewnętrznej (nazwana też poleceniem
wewnętrznym, która jest częścią samej powłoki i jest zawsze dostępna do
wykonania, to znaczy że nie potrzebuje dodatkowych plików aby się uruchomić),
jeżeli ją znajdzie w komendach wewnętrznych wykona ją. Jeśli jednak nie
zostanie znaleziona sprawdza w aktualnym katalogu (jeżeli mamy . przed
poleceniem), jeżeli znajdzie w aktualnym katalogu wykona polecenie z
aktualnego katalogu. Jeżeli nie znajdzie, powłoka sprawdzi ustawienie zmiennej
PATH, i spróbuje znaleźć żądany przez nas plik z atrybutem wykonania we
wszystkich katalogach wymienionych w ścieżce PATH, jeżeli znajdzie to ją
wykona, w innym wypadku wyświetli informację "bash: xxxx :command not found"
(polecenie nie znalezione). Jest jeszcze jedno do wyjaśnienia, czy można
uruchomić nasze skrypty tak jak wyżej wymienione pliki. Tak można, proponuję
stworzenie katalogu bin w twoim domowym katalogu i skopiować tam testowe
wersje skryptów. Po tej operacji możesz uruchamiać swoje skrypty (oczywisciwe
z ustawionym atrybutem wykopania) bez użycia składni $ ./shell nazwa_skryptu,
Wykonaj następujące kroki
$ cd
$ mkdir bin
$ cp first ~/bin
$ first
Wyjaśnienie powyżej wymienionych poleceń
| Polecenie |
Wyjaśnienie |
| $ cd |
Idź do domowego katalogu |
| $ mkdir bin |
Stwórz katalog bin, w nim zostaną zainstalowane
twoje skrypty powłoki, te skrypty będą uruchamiane jak niezależne
programy
będą dostępne z każdego katalogu |
| $ cp first ~/bin |
skopiuj swój skrypt 'first' do twojego katalogu bin |
| $ first |
Sprawdzamy czy skrypt można uruchomić |
W skryptach powłoki komentarz jest poprzedzany znakiem # . Taki komentarz
jest ignorowany przez powłokę. Komentarze używane są do opisania skryptu
przez/dla osób które tworzą/wykorzystują skrypt, lub też do opisania zagadnień
programistycznych itd.
Pamiętaj zawsze ustawiaj Atrybut wykonania dla swojego skryptu.
Polecenia związane z programowaniem w
powłoce
(1)echo [opcje] [łańcuch, zmienne...]
Wyświetla tekst lub wartości zmiennych na ekranie.
Opcje
-n Nic nie wyświetla przechodzi do następnej linii.
-e Włącza interpretację następujących komend występujących po \
(backslash):
\a dzwonek (bell)
\b backspace (kasuje ostatni znak)
\c przechodzi do następnej linii
\n nowa linia
\r powrót karetki
\t tabulator
\\ znak \ (backslash)
Na przykład. $ echo -e "An apple a day keeps away
\a\t\tdoctor\n"
(2) Więcej o cudzysłowach
Cudzysłów w skryptach występuje w trzech rodzajach:
" - podwójny cudzysłów
' - pojedynczy cudzysłów (apostrof)
` - odwrócony cudzysłów (odwrócony apostrof)
1."Podójny cudzysłów" - Cokolwiek jest zamknięte w podwójny cudzysłów
pozbawiane jest znaczenia tych znaków (z wyjątkiem \ i $).
2. 'Pojedynczy cudzysłów' - Zamknięty ciąg w pojedynczy cudzysłów pozbawiane
jest znaczenia tych znaków bez wyjątków.
3. `Odwrócony cudzysłów` - Wykonuje polecenie.
Na przykład
$ echo "Dzisiaj jest date"
Nie wyświetli informacji z dzisiejszą datą.
$ echo "Dzisiaj jest `date`".
Teraz wyświetli dzisiejszą datę, Dzisiaj jest Tue Jan ....,Obejżyj
specyfikacje polecenia `date` użytego w odwróconym cudzysłowie, (Zobacz
również Operacje arytmetyczne w powłoce).
(3) Operacje arytmetyczne w powłoce
Używanie operacji arytmetycznych w powłoce, przykłady :
$ expr 1 + 3
$ expr 2 - 1
$ expr 10 / 2
$ expr 20 % 3 # reszta z dzielenia (20 mod 3) wynosi 2)
$ expr 10 \* 3 # Mnożenie, używamy \* a nie *
$ echo `expr 6 + 3`
Dla ostatniego polecenia rozpatrzmy następujące punkty
1) Po pierwsze , przed słowem expr użyty został znak ` (odwrócony cudzysłów) a
nie znak ' (pojedynczy cudzysłów). Odwrócony cudzysłów zazwyczaj można znaleźć
na klawiszu pod znakiem tyldy (~) znajdującym się nad klawiszem TAB.
2) Po drugie, wyrażenie expr jest również zakończone znakiem ` tj. odwrócony
cudzysłów.
3) Tutaj expr 6 + 3 daje wynik 9, więc polecenie echo wyświetli 9 jako sumę
wyrażenia
4) Jeżeli użyjemy podwójnego lub pojedynczego cudzysłowie , to nie zadziała
(wyrażenie nie zostanie obliczone, Na przykład
$ echo "expr 6 + 3" # Wyświetli expr 6 + 3
$ echo 'expr 6 + 3'
Działanie linii poleceń
Wypróbujmy następujące polecenie (zakładam że plik "grate_stories_of" nie
istnieje)
$ ls grate_stories_of
Wyświetli informacje w rodzaju -
grate_stories_of: No such file or directory
To wyrzuciło ls które było nazwą aktualnego polecenia a powłoka wykonała
polecenie kiedy je otrzymała. Nasuwa się jedno pytanie Co to za polecenie? Co
się stało kiedy wpisałeś $ ls grate_stories_of?
Pierwsze słowo w linii komend, ls, jest nazwą polecenia które zostało wykonane.
Wszystko poza tym w linii komend jest uważane jako argumenty polecenia. Na
przykład
$ tail +10 myf
Tutaj nazwą polecenia jest tail, a argumentami są +10 oraz myf.
Spróbujemy wyznaczyć polecenia i argumenty z poniższych komend:
$ ls foo
$ cp y y.bak
$ mv y.bak y.okay
$ tail -10 myf
$ mail raj
$ sort -r -n myf
$ date
$ clear
|
Polecenie |
Liczba argumentów tego polecenia |
Aktualne argumenty |
| ls |
1 |
foo |
| cp |
2 |
y oraz y.bak |
| mv |
2 |
y.bak oraz y.okay |
| tail |
2 |
-10 oraz myf |
| mail |
1 |
raj |
| sort |
3 |
-r, -n, oraz myf |
| date |
0 |
|
| clear |
0 |
|
Uwaga: $# zawiera liczę argumentów wymienionych w linii poleceń. A $* oraz $@
wskazuje wszystkie argumenty podane dla skryptu. Całkowitą liczbę argumentów
dla konkretnego skryptu, masz w zmiennej $#.
Dlaczego argumenty są potrzebne
Weźmy polecenie rm, które jest używane do usuwania plików, Ale które pliki
chcesz usunąć, musisz podać jako argument dla polecenia rm (Również polecenie
rm nie zapyta cię o nazwę pliku który chcesz usunąć). Tym co zrobimy jest
wydanie polecenia w następujący sposób
$ rm {nazwa-pliku}
Tutaj rm jest poleceniem a nazwa-pliku jest plikiem który chcemy usunąć. W ten
sposób przekazałeś dla polecenia rm który plik ma usunąć. Więc mamy jedną
drogę do komunikacji z naszym poleceniem przez podanie nazwy-pliku. Możesz
także przekazać argumenty linii poleceń do swojego skryptu w sposób bardziej
przyjazny dla użytkownika.
Weźmy komendę ls
$ ls -a /*
To polecenie ma 2 argumenty -a oraz /*. Dla skryptu powłoki,
$ myshell foo bar

Nazwa skryptu powłoki tj. myshell
Pierwszy argument linii poleceń występujący
po myshell tj. foo
Drugi argument linii poleceń występujący po
myshell tj. bar
W powłoce jeśli życzymy sobie powiązania tych argumentów linii poleceń my
powiążemy powyższe w następujący sposób
myshell to jest $0
foo to jest $1
bar to jest $2
Tutaj $# będzie miało wartość 2 (Bowiem foo i bar ro tylko dwa argumenty),
Zapamiętaj, naraz te 9 argumentów może być użyte przez $0..$9, Możesz również
odwołać się do wszystkich argumentów używając $* (co oznacza `$0,$1,$2...$9`)
Spróbujmy opisać następujące polecenia w kategoriach, Nazwa skryptu ($0),
Liczba argumentów (tj. $#), i aktualne argumenty (tj. $1,$2 itd.)
$ sum 11 20
$ math 4 - 7
$ d
$ bp -5 myf +20
$ ls *
$ cal
$ findBS 4 8 24 BIG
| Nazwa skryptu powłoki |
Liczba argumentów skryptu |
Aktualne argumenty ($1,..$9) |
| $0 |
$# |
$0 |
$1 |
$2 |
$3 |
$4 |
| sum |
2 |
11 |
20 |
|
|
|
| math |
3 |
4 |
- |
7 |
|
|
| d |
0 |
|
|
|
|
|
| bp |
3 |
-5 |
myf |
+20 |
|
|
| ls |
1 |
* |
|
|
|
|
| cal |
0 |
|
|
|
|
|
| findBS |
4 |
4 |
8 |
24 |
BIG |
|
Dla przykładu teraz napiszemy skrypt który wyświetli argumenty linii poleceń i
zobaczymy jak do nich się dostać
$ cat > demo
#!/bin/sh
#
# Script that demos, command line args
#
echo "Całkowita liczba argumentów linii poleceń $#"
echo "$0 jest nazwą skryptu"
echo "$1 jest pierwszym argumentem"
echo $2 jest drugim argumentem"
echo "Wszystkie na raz :- $*"
Zapisz powyższy skrypt przez ctrl+d, i ustaw atrybut wykonania
$ chmod +x demo
$ ./demo Hello World
$ cp demo ~/bin
$ demo
Uwaga: Potem, dla każdego skryptu musisz użyć powyższych poleceń, we właściwej
kolejności (tak jak powyżej). Nie będę tego powtarzał za każdym razem.
(5) Status wyjścia
Domyślnie w Linuksie jeśli jakieś polecenie wykona się, Zwraca dwa rodzaje
wartości, (Wartości są używane do sprawdzenia czy polecenie zakończyło się
sukcesem czy nie) Jeżeli zwróconą wartością jest zero (0), polecenie
zakończyło się sukcesem, jeżeli wartość zwrócona jest niezerowa (>0),
polecenie nie wykonało się poprawnie.
Ta wartość jest nazywana Statusem wyjścia polecenia. Aby określić status
wyjścia używamy zmiennej $? . Na przykład
$ rm unknow1file
To pokaże następujący błąd
rm: cannot remove `unkowm1file': No such file or directory
a później jeśli wydasz komendę
$ echo $?
wyświetli niezerową wartość(>0) określającą numer błędu. Teraz wydaj komendę
$ ls
$ echo $?
Wyświetli 0 oznacza to że polecenie wykonało się prawidłowo. Spróbuj wykonać
poniższe komendy i obejrzyj status wyjścia tych rozkazów
$ expr 1 + 3
$ echo $?
$ echo Welcome
$ echo $?
$ wildwest canwork?
$ echo $?
$ date
$ echo $?
$ echon $?
$ echo $?
(6) Instrukcje warunkowe if-then-fi w
powłoce
Zanim zaczniemy stosować instrukcje warunkowe w skryptach musisz poznać kilka
rzeczy Napisz bc w linii poleceń aby uruchomić kalkulator
$ bc
Po wykonaniu polecenia bc program został uruchomiony i oczekuje na twoje
rozkazy, teraz podamy mu kilka obliczeń jak na przykład 5 + 2 :
5 + 2
7
kalkulator bc odpowiedział liczbą 7 czyli wynikiem dodawania 5 + 2, możesz
spróbować inne operacje :
5 - 2
5 / 2
A co się stanie jeżeli napiszemy 5 > 2 :
5 > 2
0
bc odpowiedział 0 (Zero), Dlaczego? To jest porównanie 5 z 2, Ponieważ 5 jest
większe niż 2, (Jeżeli zapytam Ciebie czy 5 jest większe od 2, ty odpowiesz
TAK) W Linuksie program bc również powiedział 'YES' pokazując wartość 0
(Zero). To znaczy że jeżeli podasz dla powłoki porównanie możesz otrzymać
tylko dwie odpowiedzi, czyli TAK lub NIE.
| Wartość powłoki Linuxa |
Znaczenie |
Przykład |
| Zero Value (0) |
Yes/True |
0 |
| Wartość niezerowa (> 0) |
No/False |
-1, 32, 55 wszystko tyo nie zero |
Aby to zrozumieć wypróbuj poniższe wyrażenia w programie bc
5 > 12
5 == 10
5 != 2
5 == 5
12 < 2
| Wyrażenie |
Znaczenie dla nas |
Twoja odpowiedz |
Odpowiedz BC (t.j. przedstwienie wrtości
zerowej lub niezerowej) |
| 5 > 12 |
5 jest większe od
12 |
NO |
0 |
| 5 == 10 |
5 jest równe 10
|
NO |
0 |
| 5 != 2 |
5 NIE jest równe
2 |
YES |
1 |
| 5 == 5 |
5 jest równe
5 |
YES |
1 |
| 1 < 2 |
1 jest mniejsze od
2 |
Yes |
1 |
Spójrzmy na poniższy przykład z zastosowaniem instrukcji warunkowej, jeżeli
warunek który jest użyty w celu decyzji o wykonaniu jakiejś pracy w powłoce,
jest prawdziwy, polecenie (command1) zostanie wykonane.
Składnia:
if warunek
then
command1 jeżeli warunek jest prawdziwy lub status wyjścia polecenia
zawartego w warunku wynosi 0 (zero)
...
...
fi
Warunek nie jest niczym więcej niż porównaniem wartości, aby
wykorzystać instrukcje warunkowe jako warunek możemy wykorzystać test,
wyrażenie [ expr ] lub też statusu wyjścia jeżeli może być użyty.
Wyrażenie jest niczym innym jak związkiem pomiędzy wartościami,
zależności operatów porównawczych (takich jak >,<, <> itd.) i operatorów
artretycznych (takich jak +, -, / itd. ). Poniżej są przykładowe wyrażenia:
5 > 2
3 + 6
3 * 65
a < b
c > 5
c > 5 + 30 -1
Wpisz następujące polecenia (zakładam że masz plik nazwany foo)
$ cat foo
$ echo $?
Polecenie cat zwróci zero(0) jako sukces, to może zostać wykorzystywane jako
warunek, Napisz skrypt tak jak poniżej
$ cat > showfile
#!/bin/sh
#
#Scrypt do wyświetlania pliku
#
if cat $1
then
echo -e "\n\nFile $1, znaleziony i wyświetlony
poprawnie"
fi
Teraz uruchomimy go.
$ chmod +x showfile
$./showfile foo
$ ./showfile foo
nasz skrypt nazywa się showfile($0) a foo jest argumentem (który jest
$1).nasze porównanie wygląda następująco
if cat $1 (to znaczy - if cat foo)
Jeżeli polecanie cat znajdzie plik foo i jeżeli wyświetlenie go na ekranie
zakończy się sukcesem, to znaczy że nasze polecenie cat zakończyło się
prawidłowo a jego status wyjściowy jest równy 0 (wskazuje poprawne
zakończenie), więc jeśli nasz warunek również jest prawdziwy wyrażenie echo
-e "\n\nFile $1, znaleziony i wyświetlony poprawnie" jest przetwarzane przez
powłokę. Jeżeli natomiast polecanie cat nie zakończy się poprawnie zwróci
niezerową wartość (informującą że coś się nie udało) i wyrażenie echo -e
"\n\nFile $1, znaleziony i wyświetlony poprawnie" zostanie pominięte przez
powłokę.
Spróbuj napisać odpowiedz na poniższe pytania
1) Stwórz poniższy skrypt
cat > trmif
#
# Skrypt do testowania polecenia rm
#
if rm $1
then
echo "$1 skasowany"
fi
(Naciśnij Ctrl + d aby zachować)
$ chmod +x trmif
Odpowiedz na następujące pytania
A) Zakładamy że w katalogu roboczym istnieje plik o nazwie foo kiedy wydajesz
komendę, $ ./trmfi foo gdzie plik foo jest parametrem. Co
wyświetli skrypt ?
B) Zakładamy że nie masz w swoim katalogu pliku bar kiedy wydajesz polecenie,
$ ./trmfi bar gdzie plik bar jest parametrem, co wyświetli
skrypt ?
C) A jeżeli napiszesz $ ./trmfi, co wyświetli skrypt ?
(7) Polecenie test lub [ wyrażenie ]
Polecenie test lub [ wyrażenie ] (otwarty i zamknięty kwadratowy nawias) jest
używany do określenia czy wyrażenie warunkowe jest prawdziwe, i jeżeli jest
prawdziwe zwraca zero(0), w przeciwnym wypadku zwraca wartość niezerową (>0).
Składnia: test wyrażenie
lub
[ wyrażenie ]
Możemy napisać skrypt który wykryje czy liczba podana jako argument jest
dodatnia. Napisz poniższy skrypt
$ cat > ispostive
#!/bin/sh
#
# Skrypt który określa czy podany argument jest dodatni
#
if test $1 -gt 0
then
echo "$1 liczba jest dodatnia"
fi
Uruchom w poniższy sposób
$ chmod +x ispostive
$ ispostive 5
Wyświetli : 5 liczba jest dodatnia
$ispostive -45
Nic nie zostanie wyświetlone
$ispostive
Wyświetli : ./ispostive: test: -gt: unary operator expected
Linia " if test $1 -gt 0 " określa czy pierwszy ($1) argument linii poleceń
jest większy niż 0. Jeżeli to prawda komenda test zwraca zero 0 a wyświetlona
zostanie linia " 5 liczba jest dodania " ale dla argumentu -45 nic nie
zostanie wyświetlone ponieważ wcześniej wymieniony warunek nie zostanie
spełniony (-45 nie jest większe niż 0) dlatego polecenie echo zostanie
pominięte. A ostatnie wyrażenie nie zostało przez nas zaopatrzone w żaden
argument dlatego został wyświetlony błąd " ./ispostive: test: -gt: unary
operator expected " wygenerowany przez powłokę , aby uniknąć takich błędów jak
ten możemy sprawdzać czy argument linii poleceń istnieje czy nie (Zobacz
polecenie 8 w przykładowym skrypcie). test lub [ expr ] pracuje z
1.Integer ( liczba całkowita - bez przecinków)
2.plikami
3.Ciągami znaków
Poniższa tabela prezentuje operatory matematyczne do wykorzystania w
skryptach
| Operator matematyczny in w skrypcie
powłoki |
Znaczenie |
normalne armetyczna/ matematyczne wyrażenie |
Ale w powłoce |
| |
|
|
dla polecnia test z komendą if |
dla polecniea [ wyrażenie ] z komendą if |
| -eq |
jest równe |
5 == 6 |
if test 5 -eq 6 |
if expr [ 5 -eq 6 ] |
| -ne |
jest różne
|
5 != 6 |
if test 5 -ne 6 |
if expr [ 5 -ne 6 ] |
| -lt |
jest mniejsze
|
5 < 6 |
if test 5 -lt 6 |
if expr [ 5 -lt 6 ] |
| -le |
jest mniejsze lub równe
|
5 <= 6 |
if test 5 -le 6 |
if expr [ 5 -le 6 ] |
| -gt |
jest większe
|
5 > 6 |
if test 5 -gt 6 |
if expr [ 5 -gt 6 ] |
| -ge |
jest większe lub równe
|
5 >= 6 |
if test 5 -ge 6 |
if expr [ 5 -ge 6 ] |
NOTE: == jest równe, != jest różne.
Dla porównania ciągów znaków używamy
| Operator |
Znaczenie |
| łańcuch1 = łańcuch2 |
łańcuch1 jest równy łańcuch2 |
| łańcuch1 != łańcuch2 |
łańcuch1 jest różny od łańcuch2 |
|
łańcuch1 |
łańcuch1 niest pusty lub nie jest zdefinowany |
| -n łańcuch1 |
łańcuch1 nie jest pusty i istnieje |
| -z łańcuch1 |
łańcuch1 jest pusty (NULL) i istnieje |
Polecenia testujące można stosować w odniesieniu do plików i katalogów
| Test |
Znaczenie |
| -s plik |
Nie pusty plik |
| -f plik |
Plik istnieje lub jest to plik nie katalog |
| -d katalog |
Katalog, nie plik |
| -w plik |
czy plik jest zapisywalny |
| -r plik |
czy plik jest tylko do odczytu |
| -x plik |
czy plik jest wykonywalny |
Operatory logiczne
Operatory logiczne można użyć do wykorzystania dwóch lub więcej warunków w
jednym czasie
|
Operator |
Znaczenie |
| ! wyrażenie |
Logiczne NIE - negacja |
| wyrażenie1 -a wyrażenie2 |
Logiczne AND |
| wyrażenie1 -o wyrażenie2 |
Logiczne OR |
(8)if...else...fi
Jeżeli podany warunek jest prawdziwy komenda1 jest wykonywana w przeciwnym
wypadku wykonywana jest komenda2.
Składnia:
if warunek
then
komenda1 jeżeli warunek jest prawdziwy
lub jeżeli status wyjścia
warunku był równy zero 0(zero)
...
...
else
komenda2 jeżeli warunek był fałszywy
lub status wyjścia
warunku był >0 (niezerowy)
...
...
fi
Dla przykładu napisz poniższy skrypt
$ cat > isnump_n
#!/bin/sh
#
# Skrypt sprawdza czy argument jest dodatni lub ujemny
#
if [ $# -eq 0 ]
then
echo "$0 : Musisz podać liczbę całkowitą"
exit 1
fi
if test $1 -gt 0
then
echo "liczba $1 jest dodatnia"
else
echo "lizba $1 jest ujemna"
fi
Spróbuj wykonać poniższe polecenia
$ chmod +x isnump_n
$ isnump_n 5
Wyświetli : liczba 5 jest dodatnia
$ isnump_n -45
Wyświetli : liczba -45 jest ujemna
$ isnump_n
Wyświetli : ./ispos_n : Musisz podać liczbę całkowitą
$ isnump_n 0
Wyświetli : liczba 0 jest ujemna
Po pierwsze zwróćmy uwagę na to że jeżeli nie podamy żadnego argumentu w linii
poleceń przy wywołaniu skryptu, wyświetlona zostanie informacja o błędzie -
"./ispos_n : Musisz podać liczbę całkowitą". W pierwszym wyrażeniu if
sprawdzamy czy argument ($#) jest równy (-eq) 0, jeżeli podaliśmy jakiś
argument dla skryptu to wyrażenie będzie fałszywe natomiast jeżeli nie było
żadnego argumentu w linii poleceń wyrażenie będzie prawdziwe. Polecenie echo w
przykładzie :
echo "$0 : Musisz podać liczbę całkowitą"
|
|
|
|
1
2
1 wyświetli nazwę skryptu
2 wyświetli informację o błędzie
I w końcu jeżeli wyrażenie będzie prawdziwe skrypt przerwie wykonywanie z
statusem wyjściowym 1 (exit 1) (niezerowa wartość oznacza że skrypt nie
zakończył się sukcesem), W ostatnim przykładzie uruchamiamy skrypt pisząc $
isnump_n 0 , co wyświetla odpowiesz "liczba 0 jest ujemna", ponieważ podany
argument nie jest > 0 (większy od zera), dlatego warunek jest fałszywy a
liczba 0 została potraktowana jako ujemna. Aby uniknąć takich sytuacji musimy
zastosować drugi warunek :
if test $1 -ge 0.
(9) Wielopoziomowy if-then-else
Składnia:
if warunek
then
warunek jest równy zero (true - 0)
wykonuje wszystkie polecenia
do wyrażenia elif
elif condition1
warunek1 jest równy 0 (true - 0)
wykonuje wszystkie polecenia
do wyrażenia elif
elif condition2
condition2 jest równy 0 (true - 0)
wykonuje wszystkie polecenia
do wyrażenia else
else
żaren z powyższych warunków nie
jest spełniony (to znaczy
wszystkie miały wartości inne niż zero)
wykonuje wszystkie polecenia
do wyrażenia fi
fi
Dla przykładu napiszemy skrypt taki jak niżej
$ cat > elf
#!/bin/sh
#
# Skrypt do testowania if..elif...else
#
#
if [ $1 -gt 0 ]
then
echo "liczba $1 jest dodatnia"
elif [ $1 -lt 0 ]
then
echo "liczba $1 jest ujemna"
elif [ $1 -eq 0 ]
then
echo "liczba $1 jest zerem"
else
echo "Opps! $1 to nie liczba, podaj liczbę"
fi
Wypróbujmy powyższy skrypt
$ chmod +x elf
$ ./elf 1
$ ./elf -2
$ ./elf 0
$ ./elf a
Wyświetlone komunikaty dal ostatniej linii przykładu:
./elf: [: -gt: unary operator expected
./elf: [: -lt: unary operator expected
./elf: [: -eq: unary operator expected
Opps! a to nie liczba, podaj liczbę
Powyższy program zakomunikował błąd przy ostatnim uruchomieniu, tutaj
oczekiwane było porównanie liczby całkowitej dlatego pojawił się taki błąd
"./elf: [: -gt: unary operator expected", ale mimo to nasz program
poinformował o złym argumencie przez wyświetlenie komunikatu "Opps! a to nie
liczba, podaj liczbę".
(10) Pętle w skryptach powłoki
Komputer może powtarzać jakiś ciąg instrukcji cały czas, dopóki jakiś
określony warunek zostanie spełniony. Taką grupę instrukcji którą program
podczas wykonania powtarza kilkukrotnie nazywa się pętlą.
(a) Instrukcje dla pętli for
Składnia:
for { nazwa zmiennej } in { lista }
do
wykonywane jest raz dla każdego elementu
na liście dopóki lista nie skończy się
(Powtarzane są wszystkie wyrażenia pomiędzy do a done)
done
Wypróbujmy,
$ cat > testfor
for i in 1 2 3 4 5
do
echo "Welcome $i times"
done
Uruchmimy to,
$ chmod +x testfor
$ ./testfor
Pętla for najpierw tworzy zmienną 'i' a następnie przydziela dla niej liczbę
po kolei z listy z zakresy od 1 do 5, Powłoka wykonuję kolejno instrukcję echo
dla każdej wartości powiązanej z i. (to zazwyczaj nazywamy pętlą) Ten proces
będzie kontynuowany dopóki wszystkie elementy listy nie zostaną użyte, w tym
przykładzie instrukcja echo będzie powtórzona 5 razy.
Wypróbujmy jeszcze poniższy skrypt
$ cat > mtable
#!/bin/sh
#
#Skrypt do testowania pętli
#
#
if [ $# -eq 0 ]
then
echo "Błąd - Nie znaleziono liczby jako argumentu"
echo "Składnia : $0 liczba"
echo " Wyświetla tablicę mnożenia dla
podanego argumentu"
exit 1
fi
n=$1
for i in 1 2 3 4 5 6 7 8 9 10
do
echo "$n * $i = `expr $i \* $n`"
done
Zapisz i uruchom
$ chmod +x mtable
$ ./mtable 7
$ ./mtable
Przy pierwszym uruchomieniu, powyższy program wyświetla tablicę mnożenia
podanej liczby gdzie i = 1,2 ... 10 jest mnożone przez podane n (tutaj
argumentem było 7) kolejno zostanie wyświetlona tablica jak poniżej
7 * 1 = 7
7 * 2 = 14
...
..
7 * 10 = 70
Przy drugim uruchomieniu zostaną wyświetlone komunikaty -
Błąd - Nie znaleziono liczby jako argumentu
Składnia : ./mtable liczba
Wyświetla
tablicę mnożenia dla podanego argumentu
Tak się stało bo nie podaliśmy żadnej liczby którą można było użyć przy
tworzeniu tablicy mnożenia, Dlatego został wyświetlony błąd, składnia i
informacja o działaniu. TO jest dobry pomysł jeżeli nasz program wymaga jakiś
argumentów, niech użytkownik wie jakie argumenty są potrzebne do pracy skryptu
i jak ich użyć. Tutaj do przerwania pracy naszego skryptu użyliśmy polecenia
'exit 1' które jest z argumentem 1 (1 wskazuje błąd dlatego skrypt jest
przerywany)
(b)pętla while
Składnia:
while [ warunek ]
do
polecenie1
polecenie2
polecenie3
....
....
done
Pętla będzie wykonywana tak długo jak podany warunek będzie prawdziwy. Dla
przykładu powyżej napisany skrypt dla pętli for możemy przepisać dla pętli
while, tak jak poniżej
$cat > nt1
#!/bin/sh
#
#Skrypt do testowania wyrażenia while
#
#
if [ $# -eq 0 ]
then
echo "Błąd - Nie znaleziono liczby jako argumentu"
echo "Składnia : $0 liczba"
echo " Wyświetla tablicę mnożenia dla podanego
argumentu"
exit 1
fi
n=$1
i=1
while [ $i -le 10 ]
do
echo "$n * $i = `expr $i \* $n`"
i=`expr $i + 1`
done
Zapiszmy i wyrpóbujmy
$ chmod +x nt1
$./nt1 7
Powyżej napisany skryp możemy wyjaśnić w następujący sposób
| n=$1
|
Ustawia wartość zmiennej n według podanego argumentu w linii poleceń. (Tutja
jest to 7 )
|
| i=1
|
Ustawia wartość zmeinnej i na 1
|
| while [ $i -le 10
]
|
To jest warunek naszej pętli, jeżeli wartość i jest mniejsza niż 10 to,
powłoka wykona wszystkie instrukcje zawarte pomiędzy do a done |
| do
|
Początek pętli
|
| echo "$n * $i = `expr
$i \* $n`" |
Wyświetla tebliczkę mnożenia
7 * 1 = 7
7 * 2 = 14
....
7 * 10 = 70, Tutaj za każdym razem wartość zmiennej n jest mnożone przez
i. |
| i=`expr $i +
1` |
Zwiększamy wartość zmiennej i o 1 i zapisujemy rezultat w zmiennej i.
(t.j. i=i+1)
Uwaga: Jeżeli zignorujemy
(wyrzucimy) to wyrażenie
nasza pętla będzie działała w nieskończoność ponieważ wartość zmiennej i
zawsze będzie mniejsza od 10
a program będzie wyświetlał tylko
7 * 1 = 7
7 * 1 = 7
...
...
E (nieskończoną ilość razy) |
|
done |
Tutaj pętla się kończy i jeżeli zmienna i nie jest mniejsza od 10, to
znaczy warunek pętli nie jest prawdziwy. Nasza
pętla jest przerywana.
|
Jeszcze kilka uwag o pętlach
(a) Po pierwsze, zmienne użyte w warunkach pętli muszą być zainicjalizowane,
inaczej nie zostanie wykonana pętla.
(b) Test (warunek) jest wykonywany na początku każdego powtórzenia.
(c) Ciało (zawartość) pętli kończy się wyrażeniem które modyfikuje wartość
testowanych w warunku zmiennych.
(11) Wyrażenie case
Wyrażenie case jest dobrą alternatywą dla wielopoziomowych warunków
if-then-else-fi. Pozwala wykorzystać wile różnych wartości możliwych dla
jednej zmiennej variable. Jest łatwe do czytania i zapisania.
składnia:
case $nazwa-zmiennej in
wzór1) polecenie
...
..
polecenie;;
wzór2) polecenie
...
..
polecenie;;
wzórN) polecenie
...
..
polecenie;;
*) polecenie
...
..
polecenie;;
esac
Zmienna $nazwa-zmiennej jest porównywana do wymienionych wzorów dopóki nie
zostanie znaleziony odpowiednik. Powłoka wykonuj wtedy wszystkie polecenia aż
do znalezienie podwójnego średnika. Domyślną wartością jest *) i jest on
wykonywany w momencie kiedy nie został znaleziony żadne wzorzec. Stworzymy
skrypt tak jak poniżej
$ cat > car
#
# Jeżeli nie została podana żadna nazwa pojazdu
# tj. -z $1 jest zdefiniowany i jest równy NULL
#
# jeżeli nie ma żadnych arguentów w linii poleceń
if [ -z $1 ]
then
rental="*** Unknown vehicle ***"
elif [ -n $1 ]
then
# w innym wypadku bierzemy pierwszy argument jako rental
rental=$1
fi
case $rental in
"car") echo "For $rental Rs.20 per k/m";;
"van") echo "For $rental Rs.10 per k/m";;
"jeep") echo "For $rental Rs.5 per k/m";;
"bicycle") echo "For $rental 20 paisa per k/m";;
*) echo "Sorry, I can not gat a $rental for you";;
esac
Zapisz skryp przez nacisnięcie CTRL+D
$ chmod +x car
$ car van
$ car car
$ car Maruti-800
Po pierwsze sprawdzamy, czy $1(pierwszy argument linii poleceń) jest obecny,
jeżeli nie ustawiamy wartość zmiennej rental na "*** Unknown vehicle
***",jeżeli argument został podany ustawiamy wartość pierwszego argumentu w
zmiennej rental. Zmienna $rental jest porównywana do podanych wzorców dopóki
nie zostanie znaleziony odpowiednik. W podanym przykładzie dla pierwszego
uruchomienia została znaleziona wartość van Więc skrypt wyświetlił informację
" For van Rs.10 per k/m ". Przy drugim uruchomieniu została wyświetlona
informacja "For car Rs.20 per k/m". A przy ostatnim uruchomieniu nie
znaleziono odpowiednika "Maruti-800", więc wykonano domyślne instrukcje tj. *)
wyświetla "Sorry, I can not gat a Maruti-800 for you". Wyrażenie esac jest
zawsze wymagane oznaczając koniec polecenia case.
(12) Wyrażenie read
Używa się do pobierania danych z klawiatury i zapisywania w zmiennych.
Składnia: read zmienna1, zmienna2,...zmiennaN
Stworzymy skrypt według :
$ cat > sayH
#
#Skrypt przeczyta twoje imię wprowadzone z klawiatury
#
echo "Podaj swoje imię:"
read fname
echo "Hello $fname, zostańmy przyjaciółmi!"
Uruchom go w poniższy sposób
$ chmod +x sayH
$ ./sayH
Ten skrypt najpierw zapyta o imię i poczeka aż użytkownik je wprowadzi, Kiedy
użytkownik wpisze swoje imię (po podaniu imienia musisz nacisnąć ENTER)
wprowadzone imię jest zapisywane do zmiennej fname.
(13) Znaki specjalne
* lub ? lub [...] są znakami specjalnymi.
* Znajduje każdy łańcuch znaków z grupy liter.
Na przykład $ ls * , pokaże wszystkie pliki, $ ls a* - pokaże
wszystkie pliki których nazwa rozpoczyna się na literę 'a', $ ls *.c
,pokaże wszystkie pliki mające rozszerzenie .c
$ ls ut*.c, pokaże wszystkie pliki mające rozszerzenie .c ale
zaczynające się od liter 'ut'.
? Znajduje pojedynczy znak.
Na przykład $ ls ? , Pokaże tylko te nazwy plików które składają się z
jednej litery, $ ls fo? , pokaże wszystkie pliki które mają trzy znaki
a ich nazwa zaczyna się od liter fo
[...] Znajduje każdą z wyszczególnionych liter.
Na przykład $ ls [abc]* - pokaże wszystkie pliki zaczynające się od
znaków a,b,c
[..-..] Para znaków przedzielona minusem oznacza zakres;
Na przykład $ ls /bin/[a-c]* - pokaże wszystkie pliki zaczynające się od
znaków a,b oraz c jak poniżej
/bin/arch /bin/awk /bin/bsh /bin/chmod /bin/cp
/bin/ash /bin/basename /bin/cat /bin/chown /bin/cpio
/bin/ash.st /bin/bash /bin/chgrp /bin/consolechars /bin/csh
Ale
$ ls /bin/[!a-o]
$ ls /bin/[^a-o]
Jeżeli pierwszą literą, zaraz po znaku [, jest ! lub ^ to podany zakres
znaków ma zostać wykluczony, więc nie pokaże na m plików zaczynających się do
a,b,c,e...o, jak poniżej
/bin/ps /bin/rvi /bin/sleep /bin/touch /bin/view
/bin/pwd /bin/rview /bin/sort /bin/true /bin/wcomp
/bin/red /bin/sayHello /bin/stty /bin/umount /bin/xconf
/bin/remadmin /bin/sed /bin/su /bin/uname /bin/ypd
/bin/rm /bin/setserial /bin/sync /bin/userconf /bin/zcat
/bin/rmdir /bin/sfxload /bin/tar /bin/usleep
/bin/rpm /bin/sh /bin/tcsh /bin/vi
(14)polecenie1;polecenie2
Służy do uruchomienia dwóch poleceń w jednej linii. Na przykład $
date;who ,Wyświetli dzisiejszą datę z zaraz za nią użytkownika który jest
aktualnie zalogowany. Nie można napisać $ date who, musisz wstawić średnik
pomiędzy polecenia date i who.
(c) 1998-2000 FreeOS.com (I) Pvt. Ltd. All rights
reserved.
Tłumaczył Robert Sobieski
2000-11-05
|
|
|