Powrót
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.
Tłumaczył Robert Sobieski
2000-11-05
Powrót