Wyklad PI 5


UNIX
Kurs początkowy
Dr inż. Lucjan Miękina
upel.agh.edu.pl/wimir/login/
Katedra Robotyki i Mechatroniki
November 5, 2012
1/19
System operacyjny UNIX
Skrypty
Czytanie z wejścia
Skrypty dotąd demonstrowane nie posiadały możliwości interakcji z użytkownikiem 
co jest możliwe do zrealizowania przez odczyt danych wejściowych wprowadzanych
przez użytkownika.
read  odczyt standardowego wejścia Na przykład:
Wbudowane polecenie read wczytuje
1 #!/bin/bash
2 # ReadInts: read the value to an integer
całą linię z wejścia standardowego.
3 echo -n "Please enter an integer -> "
Polecenie może być stosowane do
4 read int
wprowadzania danych z klawiatury lub,
5
6 if [
po przekierowaniu, z pliku. Polecenie -z "$int" ]; then
7 echo "int is empty." >&2
read ma składnię:
8 exit 1
read [-opcje] [zmienna...] 9 fi
10 if [ $int -eq 0 ]; then
gdzie opcje składają się z podanych
11 echo "int is zero."
dalej opcji, a zmienna jest nazwą jed- 12 else
13 if [ $int -lt 0 ]; then
nej lub więcej zmiennych, do których
14 echo "int is negative."
wprowadzone zostaną dane.
15 else
Gdy nie podaje się zmiennych, cała
16 echo "int is positive."
17 fi
linia zostanie wprowadzona do zmien-
18 if [ $((int % 2)) -eq 0 ]; then
nej REPLY powłoki.
19 echo "int is even."
Ogólnie, read podstawia kolejne
20 else
pola wprowadzone ze stdin do 21 echo "int is odd."
22 fi
wymienionych zmiennych.
23 fi
2/19
System operacyjny UNIX
Skrypty
Opcje polecenia read
Polecenie read akceptuje następujące opcje:
-a array wprowadz dane do tablicy array, zaczynając od indeksu (pozycji) zero
-d limit traktuj pierwszy znak łańcucha limit jako znacznik końca danych wejściowych,
zamiast znaku nowej linii
-e użyj funkcji Readline do obsługi wejścia. Pozwala to na edycję danych w ten sam
sposób co w linii poleceń powłoki
-n num czytaj pierwsze num znaków z wejścia, zamiast całej linii
-p prompt wyświetl prompt wejściowy taki jak łańcuch prompt
-r tryb surowy. Nie interpretuj znaku \ jako escape.
Na przykład:
1 #!/bin/bash
2 # read multiple values from keyboard
3 echo -n "Enter one or more values > "
4 read var1 var2 var3
5 echo "var1 = $var1"
6 echo "var2 = $var2"
7 echo "var3 = $var3"
lm@arch:~% ./ReadMulti
Enter one or more values > 1 2 3
var1 = 1
var2 = 2
var3 = 3
3/19
System operacyjny UNIX
Skrypty
Przykład programu sterowanego za pomocą menu, gdzie użytkownikowi wyświetlona
zostaje lista opcji i wybiera on jedną z nich.
lm@arch:~% ./ReadMenu
1 #!/bin/bash Please Select:
2 # ReadMenu: a menu-driven sys info
1. Display System Information
3 clear
2. Display Disk Space
4 echo "
3. Display Home Space Utilization
5 PleaseSelect:
0. Quit
6 1. Display System Information
7 2. Display Disk Space
Enter selection [0-3] > 1
8 3. Display Home Space Utilization
9 0. Quit Hostname: arch
10 "
15:07:06 up 50 min, 2 users, load average: 0,32,
11 read -p "Enter selection [0-3] > "
lm@arch:~% ./ReadMenu
12 if [[ $REPLY =~ ^[0-3]$ ]]; then
13 if [[ $REPLY == 0 ]]; then
Enter selection [0-3] > 2
14 echo "Program terminated."
Filesystem Size Used Avail. %Used Mount
15 exit
rootfs 31G 8,9G 20G 31% /
16 fi
17 if [[ $REPLY == 1 ]]; then /dev/sda3 86G 14G 68G 17% /home
18 echo "Hostname: $HOSTNAME"
...
19 uptime
lm@arch:~% ./ReadMenu
20 elif [[ $REPLY == 2 ]]; then
21 df -h
Enter selection [0-3] > 3
22 elif [[ $REPLY == 3 ]]; then
Home Space Utilization (lm)
23 echo "Home Space Utilization ($USER)"
14G /home/lm
24 du -sh $HOME
25 fi
26 else
27 echo "Invalid entry." >&2
28 exit 1
29 fi
4/19
System operacyjny UNIX
Skrypty
Pętla while
Składnia polecenia while jest następująca:
while polecenia; do polecenia; done
Działanie pętli while określa kod zakończenia poleceń występujących między słowami
while i do (w poleceniu test). Jeśli jest on równy zeru, wykonywane są polecenia
wewnątrz pętli. W skrypcie, zmienna cnt po utworzeniu ma wartość 1. Po 4
iteracjach, zmienna cnt ma wartość 4, a polecenie test zwraca kod zakończenia różny
od zera, co powoduje zakończenie pętli. Program kontynuuje się wykonując następne
polecenie po końcu pętli.
1 #!/bin/bash 1 #!/bin/bash
2 # WhileLoop: display a series of numbers 2 # VariableWhileLoop: a loop with variable # of iterations
3 cnt=1 3 read -p "Enter max. number of iterations > "
4 while [ $cnt -le 3 ]; do 4 cnt=1
5 echo $cnt 5 while [ $cnt -le $REPLY ]; do
6 cnt=$((cnt + 1)) 6 echo $cnt
7 done 7 cnt=$((cnt + 1))
8 echo "Finished." 8 done
9 echo "Finished."
lm@arch:~% ./WhileLoop
lm@arch:~% ./VariableWhileLoop
1
Enter max. number of iterations > 2
2
1
3
2
Finished.
Finished.
5/19
System operacyjny UNIX
Skrypty
Pętla until
Polecenie until jest podobne do while, z tą różnicą że pętla until wykonuje się dopóki
kod zakończenia ostatniego polecenia sterującego jest różny od zera. Składnia
polecenia until jest następująca:
until polecenia; do
polecenia;
done
W skrypcie WhileLoop pętla wykonuje się dopóki wartość zmiennej cnt jest mniejsza
lub równa 3. Identyczny rezultat można osiągnąć za pomocą pętli until:
lm@arch:~% ./UntilLoop
1 #!/bin/bash 1
2 # UntilLoop: display a series of numbers
2
3 cnt=1
3
4 until [ $cnt -gt 3 ]; do
Finished.
5 echo $cnt
6 cnt=$((cnt + 1))
7 done
8 echo "Finished."
6/19
System operacyjny UNIX
Skrypty
Odczyt plików z użyciem pętli
Polecenia while i until mogą korzystać z wejścia standardowego. Pozwala to
przetwarzać pliki z użyciem tych pętli. Na przykład, aby wyświetlić zawartość pliku
GPS.txt:
1 Cracow 50.182633, 19.920554
2 Zielonki 50.282633, 19.950554
3 Narama 50.382633, 19.980554
1 #!/bin/bash
2 # WhileReadsFile: read lines from a file
3 while read location length width; do
4 printf "Location: %s\tLength: %s\tWidth: %s\n" \
5 $location \
6 $length \
7 $width
8 done < GPS.txt
lm@arch:~% ./WhileReadsFile
Location: Cracow Length: 50.182633, Width: 19.920554
Location: Zielonki Length: 50.282633, Width: 19.950554
Location: Narama Length: 50.382633, Width: 19.980554
7/19
System operacyjny UNIX
Skrypty
Pętle w potokach
Pętla może być odbiorcą danych w potoku:
1 #!/bin/bash
2 # WhileInPipe: using while in a pipe
3 sort -k 1,1 GPS.txt | while read location length width; do
4 printf "Location: %s\tLength: %s\tWidth: %s\n" \
5 $location \
6 $length \
7 $width
8 done
lm@arch:~% ./WhileInPipe
Location: Cracow Length: 50.182633, Width: 19.920554
Location: Narama Length: 50.382633, Width: 19.980554
Location: Zielonki Length: 50.282633, Width: 19.950554
8/19
System operacyjny UNIX
Skrypty
Pętla for
Pętla for w odróżnieniu od while i until pozwala przetwarzać ciągi danych sterujących.
Z tego powodu jest szczególnie popularną konstrukcją skryptów bash. Nowsze wersje
powłoki bash obsługują 2 odmiany for : tradycyjną i pochodzącą z języka C.
Tradycyjna pętla for
Oryginalna składnia pętli for jest następująca:
for zmienna [in elementy]; do
polecenia
done
gdzie zmienna jest nazwą zmiennej, która będzie podlegała zmianom w czasie
realizacji pętli, elementy to opcjonalna lista elementów, które są kolejno podstawiane
do zmiennej, a polecenia są ciągiem poleceń wykonywanych w każdym obiegu pętli.
lm@arch:~% ./ForTraditional
1 #!/bin/bash C
2 for i in C C++ Java Scala; do
C++
3 echo $i;
Java
4 done
Scala
lm@arch:~% ./ForRanges
1 #!/bin/bash
2 for i in {B..D}; do B
3 echo $i;
C
4 done
D
9/19
System operacyjny UNIX
Skrypty
Pętla for pochodzącą z języka C
Nowsze wersje powłoki bash wprowadzają drugą wersję pętli for, o składni
przypominającej pętlę for języka C. Wspiera ją także wiele innych języków:
for (( wyrazenie1; wyrazenie2; wyrazenie3 )); do
polecenia
done
gdzie wyrazenie1, wyrazenie2 i wyrazenie3 wyrażeniami arytmetycznymi, a polecenia
są poleceniami wykonywanymi w czasie każdego obiegu pętli. Co do działania,
odpowiada to następującym poleceniom:
(( wyrazenie1 ))
while (( wyrazenie2 )); do
polecenia
(( wyrazenie3 ))
done
wyrazenie1 jest używane do inicjalizacji pętli, wyrazenie2 jest używane do określenia
warunku zakończenia pętli, a wyrazenie3 jest wykonywane na zakończenie każdego
obiegu pętli.
lm@arch:~% ./ForCLang
1 #!/bin/bash 0
2 # ForCLang : demo of C style for command
1
3 for (( i=0; i<5; i=i+1 )); do
2
4 echo $i
3
5 done
4
10/19
System operacyjny UNIX
Skrypty
Parametry pozycyjne
Powłoka obsługuje zbiór zmiennych nazywanych parametrami pozycyjnymi (positional
parameters), które zawierają poszczególne ciągi wprowadzone z linii poleceń.
Parametry są nazwane cyframi 0 do 9. Na przykład:
lm@arch:~% ./PositionalPars p1 3.1415
1 #!/bin/bash $0 = ./PositionalPars
2 # PositionalPars: view command line parameters
$1 = p1
3 echo "
$2 = 3.1415
4 \$0 = $0
$3 =
5 \$1 = $1
6 \$2 = $2
7 \$3 = $3
8 "
UWAGA: można przekazać i odczytać wewnątrz skryptu większą ilość wartości,
otaczając odpowiednią liczbę nawiasami klamrowymi, na przykład ${10}, ${55} itd.
Odczyt ilości argumentów
Powłoka posiada zmienną $#, która przechowuje ilość argumentów polecenia:
1 #!/bin/bash
lm@arch:~% ./PositionalParsCnt 1 2 3
2 # PositionalParsCnt: view the number of argumentss
Number of arguments: 3
3 echo "Number of arguments: $#"
11/19
System operacyjny UNIX
Skrypty
Parametry pozycyjne: shift  dostęp do wielu argumentów
Polecenie shift przesuwa parametry o jedną pozycję w dół za każdym razem, gdy jest
wykonywane. Po każdym wykonaniu shift, wartość $2 jest przesunięta do $1, wartość
$3 jest przesunięta do $2 itd. Wartość $# jest zmniejszona o jeden.
W przykładzie tworzona jest pętla, która określa ilość argumentów pozostałych do
odczytu i wykonuje się dopóki jest jeszcze argument. W każdym obiegu pętli
wyświetlany jest bieżący argument, zwiększana jest wartość zmiennej cnt (bieżąca
ilość przetworzonych argumentów) i ostatecznie, wykonuje się polecenie shift by
załadować do $1 następny argument.
1 #!/bin/bash
2 # PositionalParsLoop: display all arguments
3 cnt=1
4 while [[ $# -gt 0 ]]; do
5 echo "Argument $cnt = $1"
6 cnt=$((cnt + 1))
7 shift
8 done
9
lm@arch:~% ./PositionalParsLoop p1 p2 p3 p4 p5
Argument 1 = p1
Argument 2 = p2
Argument 3 = p3
Argument 4 = p4
Argument 5 = p5
12/19
System operacyjny UNIX
Skrypty
Parametry pozycyjne: przekazywanie argumentów do funkcji powłoki
Przykład ilustruje przekazywanie parametru do funkcji powłoki.
1 #!/bin/bash
2 # FileInfoFun: a script using shell f. with parameter
3 FileInfo () {
4 # file_info: function to display file information
5 echo "SHELLF: \$0 = $0, \$1 = $1, \$2 = $2"
6 if [[ -e $1 ]]; then
7 echo -e "\nFile Type:"
8 file $1
9 echo -e "\nFile Status:"
10 stat $1
11 else
12 echo "$FUNCNAME: usage: $FUNCNAME file" >&2
13 return 1
14 fi
15 }
16 echo "SCRIPT: \$0 = $0, \$1 = $1, \$2 = $2"
17 FileInfo $2
lm@arch:~% ./FileInfoFun dummy FileInfoFun
SCRIPT: $0 = ./FileInfoFun, $1 = dummy, $2 = FileInfoFun
SHELLF: $0 = ./FileInfoFun, $1 = FileInfoFun, $2 =
File Type:
FileInfoFun: Bourne-Again shell script, ASCII text executable
File Status:
File:  FileInfoFun
size: 462 blocks: 8 blocks I/O: 4096 regular file
13/19
Device: 803h/2051d inode: 3932636 links: 1
System operacyjny UNIX
Skrypty
Tablice
Tablice są zmiennymi, które przechowują więcej niż jedną wartość. Tablice składają się
z komórek, zwanych elementami, a każdy element zawiera daną. Poszczególne
elementy są dostępne za pomocą adresu zwanego indeksem.
Tablice w sensie powłoki bash są ograniczone do jednego wymiaru - są w istocie
wektorami.
Tworzenie tablic
Zmienne tablicowe nazywa się podobnie jak inne zmienne powłoki bash, a tworzone są
one automatycznie w momencie pierwszego użycia:
lm@arch:~% a[2]=a2
lm@arch:~% echo ${a[2]}
a2
Tablice można też deklarować z użyciem polecenia declare:
lm@arch:~% declare -a a
14/19
System operacyjny UNIX
Skrypty
Podstawianie wartości do tablic
Podstawianie wartości może się odbyć na dwa sposoby.
Pojedyncze wartości podstawia się zgodnie ze składnią:
nazwa[indeks]=wartosc
gdzie nazwa jest nazwą tablicy, a indeks jest liczbą całkowitą (lub wyrażeniem
arytmetycznym) większym lub równym zeru. UWAGA: pierwszy element tablicy ma
indeks zero, a nie jeden. wartosc jest łańcuchem lub daną całkowitą która ma być
przypisana do elementu.
Wiele wartości można przypisać zgodnie ze składnią:
nazwa=(wartosc1 wartosc2 ...)
gdzie nazwa jest nazwą tablicy, a wartosc1 wartosc2 ... są wartościami kolejno
przypisywanymi do elementów tablicy, poczynając od elementu zero. Na przykład,
chcąc podstawić skrócone angielskie nazwy dni tygodnia do tablicy days, należy:
lm@arch:~% days=(Sun Mon Tue Wed Thu Fri Sat)
Można również przypisać wartości do wybranych elementów, podając indeks dla każdej
wartości:
lm@arch:~% days=([0]=Sun [1]=Mon [2]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)
15/19
System operacyjny UNIX
Skrypty
Operacje tablicowe: wyświetlanie całej zawartości tablic
Indeksy * i @ mogą być użyte do dostępu do wszystkich elementów tablicy. Notacja z
użyciem @ jest bardziej użyteczna. Na przykład:
lm@arch:~% people=("John Scofield" "Pat Metheny" "John McLaughlin")
lm@arch:~% for i in ${people[*]}; do echo $i; done
John
Scofield
Pat
Metheny
John
McLaughlin
lm@arch:~% for i in ${people[@]}; do echo $i; done # IDENTICAL
...
lm@arch:~% for i in "${people[*]}"; do echo $i; done
John Scofield Pat Metheny John McLaughlin
lm@arch:~% for i in "${people[@]}"; do echo $i; done
John Scofield
Pat Metheny
John McLaughlin
Działanie notacji ${people[*]} i ${people[@]} jest identyczne, o ile nie występują
one w cudzysłowie. Notacja * generuje wiersz zawierający wszystkie elementy tablicy,
podczas gdy notacja @ generuje trzy słowa, zawierające  rzeczywiste elementy.
16/19
System operacyjny UNIX
Skrypty
Operacje tablicowe: odczyt ilości elementów tablicy
Odczytu ilości elementów tablicy dokonuje się podobnie jak odczytu długości łańcucha
znaków:
lm@arch:~% echo ${#people[@]} # ilosc elementow
3
lm@arch:~% echo ${#people[0]} # rozmiar elementu 0
13
lm@arch:~% a[10]=ten # tablica o jednym elemencie o indeksie 10
lm@arch:~% echo ${#a[@]}
1
Pomimo przypisania łańcucha  ten do elementu tablicy o indeksie 10, powłoka bash
traktuje tablicę jako jednoelementową. Jest to odmienne od większości języków
programowania, w których nie używane elementy tablicy (od 0 do 9) byłyby
zainicjowane domyślnymi wartościami i wliczone w jej rozmiar.
Operacje tablicowe: znajdowanie użytych indeksów
Ponieważ bash pozwala na istnienie wolnych miejsc w tablicy, może być interesujące
które elementy rzeczywiście istnieją. Można to osiągnąć za pomocą wyrażeń:
${!tab[*]} lub ${!tab[@]} , gdzie tab jest nazwą zmiennej tablicowej.
lm@arch:~% sparse=([1]=at1 [3]=at3)
lm@arch:~% for i in "${!sparse[@]}"; do echo $i; done
1
3
lm@arch:~% for i in "${sparse[@]}"; do echo $i; done
at1
at3
17/19
System operacyjny UNIX
Skrypty
Operacje tablicowe: dodawanie elementów na końcu tablicy
Używając operatora przypisania +=, można dołączyć elementy na końcu tablicy.
lm@arch:~% people=(Scofield Metheny McLaughlin)
lm@arch:~% echo ${people[@]}
Scofield Metheny McLaughlin
lm@arch:~% people+=(Santana Hendrix)
lm@arch:~% echo ${people[@]}
Scofield Metheny McLaughlin Santana Hendrix
Operacje tablicowe: sortowanie
Powłoka nie posiada wbudowanej operacji sortowania, ale można to łatwo uzyskać
wykorzystując istniejące polecenia:
lm@arch:~% echo "Original array: ${people[@]}"
Original array: Scofield Metheny McLaughlin Santana Hendrix
lm@arch:~% sorted=($(for i in "${a[@]}"; do echo $i; done | sort))
lm@arch:~% sorted=($(for i in "${people[@]}"; do echo $i; done | sort))
lm@arch:~% echo "Sorted array: ${sorted[@]}"
Sorted array: Hendrix McLaughlin Metheny Santana Scofield
18/19
System operacyjny UNIX
Skrypty
Operacje tablicowe: usuwanie tablic
Aby usunąć całą tablicę, używa się polecenia unset:
lm@arch:~% echo "Sorted array: ${sorted[@]}"
Sorted array: Hendrix McLaughlin Metheny Santana Scofield
lm@arch:~% unset sorted
lm@arch:~% echo "Sorted array: ${sorted[@]}"
Sorted array:
Operacje tablicowe: usuwanie elementu tablicy
unset pozwala także na usuwanie pojedynczego elementu tablicy:
lm@arch:~% echo "Original array: ${people[@]}"
Original array: Scofield Metheny McLaughlin Santana Hendrix
lm@arch:~% unset  people[3]
lm@arch:~% echo "Original array: ${people[@]}"
Original array: Scofield Metheny McLaughlin Hendrix
W przykładzie usunięto czwarty element tablicy. UWAGA: nazwa elementu tablicy
musi występować w apostrofach aby powłoka nie zastosowała mechanizmu rozwijania
nazw plików (pathname expansion).
Przypisanie wartości pustej do zmiennej tablicowej nie powoduje jej opróżnienia:
lm@arch:~% echo "Original array: ${people[@]}"
Original array: Scofield Metheny McLaughlin Hendrix
lm@arch:~% people=
lm@arch:~% echo "Original array: ${people[@]}"
Original array: Metheny McLaughlin Hendrix
Każde odwołanie do zmiennej tablicowej bez podania indeksu odnosi się do elementu
o indeksie zero.
19/19


Wyszukiwarka

Podobne podstrony:
Wyklad PI 1 cz 2
Wyklad PI
Wyklad PI 9
Wyklad PI 3
Wyklad PI 2 cz 2
Wyklad PI 4
Wyklad PI 8
Wyklad PI 2 cz 1
Wyklad PI
Sieci komputerowe wyklady dr Furtak
Wykład 05 Opadanie i fluidyzacja
WYKŁAD 1 Wprowadzenie do biotechnologii farmaceutycznej
mo3 wykladyJJ

więcej podobnych podstron