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