Systemy operacyjne

Opis zajęć i zasad

Zajęcia 5

Cytowania *

Wyróżniamy nastepujące znaki cytowania:

" "

Między cudzysłowami umieszcza się tekst, wartości zmiennych zawierające spacje. Cudzysłowy zachowują znaczenie specjalne trzech znaków:

$ wskazuje na nazwę zmiennej, umożliwiając podstawienie jej wartości

\ znak maskujący

` ` odwrotny apostrof, umozliwia zacytowanie polecenia

x=2
echo "Wartość zmiennej x to $x"    #wydrukuje Wartość zmiennej x to 2
echo "Nowa linia\n\n" # przełącznik -e włącza interpretację znaków specjalnych
echo -e "Nowa linia\n\n" # przełącznik -e włącza interpretację znaków specjalnych
echo "Polecenie date pokaże: `date`"

' '

Wszystko co ujęte w znaki apostrofu traktowane jest jak łańcuch tekstowy, apostrof wyłącza interpretowanie wszystkich znaków specjalnych, traktowane są jak zwykłe znaki.

echo '$USER'   #nie wypisze twojego loginu
echo `echo ala`

` `

Odwrotny apostrof (ang. backquote) umożliwia zacytowanie polecenia, bardzo przydatne jeśli chce się podstawić pod zmienną wynik jakiegoś polecenia np:

x=`ls -la $PWD`
echo $x  # pokaże rezultat polecenia

[]

Nawiasy \([]\) testują warunek, zapisany wynik można podejrzeć w zmiennej \(\$?\). Zwraca 0 dla prawdy i 1 dla fałszu.

[ "abc" != "def" ]; echo $?
[ "abc" = "def" ]; echo $?
[ "abc" \< "def" ]; echo $?
[ "abc" \> "def" ]; echo $?
[ "abc" \<"abc" ]; echo $?
[ "abc" \> "abc" ]; echo $?

Różnica między [] a [[]], przykład

[[ "$HOME" = /home/* ]]; echo $? # nie do wykonania przy []
["$HOME" = /home/* ]; echo $?

Analigicznie zamiast [] możemy użyć komendy test

test 3 -lt 1; echo $? # -lt sprawdza czy wartość jest mniejsza_równa drugiej (patrz niżej)
test 3 -lt 5; echo $?

Skrypty

Zmienne tablicowe

Bash pozwala na stosowanie zmiennych tablicowych jednowymiarowych.

zmienna=(wartosc_1 wartosc_2 wartosc_3 wartosc_n)

Przykład:

tablica=(element1 element2 element3)

echo ${tablica[0]}
echo ${tablica[1]}
echo ${tablica[2]}

Podobnie jak w C++ elementy są indeksowane od \(0\) do \(n\). nazwa zmiennej tablicowej wskazuje na pierwszy element

echo ${tablica}

Odwołanie poza zakres tablicy zwróci nam pusty ciąg znaków. Do elementów tablicy możemy odwołać się także przez @ lub *.

echo ${tablica[@]} #zwraca wszystkie elementy tablicy
echo ${tablica[*]} #zwraca wszystkie elementy tablicy
tablica[5]=5
echo ${tablica[*]} # zwroc uwage ze elementy bez wartosci tablica[3] i tablica[4] sa zapisane jako pusty ciag znakow

Można też uzyskać długość (liczba znaków) danego elementu tablicy:

echo ${#tablica[1]}
echo ${#tablica[5]}
echo ${#tablica[*]} # podaje liczbe elementów w tablicy

gdy nie istnieje zmienna tablicowa do której dodajemy jakiś element, to BASH automatycznie ją utworzy:

nowa[0]=zero
nowa[1]=jeden

echo ${nowa[@]} # Utworzona została tablica *nowa* zawierająca dwa elementy.

Usuwanie tablicy:

unset tablica[2] # usuwa element
echo ${tablica[*]}
unset tablica[*] # usuwa całą tablice

Operacje arytmetyczne

Mechanizm interpretacji wyrażeń arytmetycznych w bash: Obliczenia dokonywane są na liczbach całkowitych, nie przeprowadzana jest kontrola przepełnienia. Składnia:

$((wyrażenie)) # lub
$[wyrażenie]

Przykład:

echo $((8/2))
wynik=$[4*5/2]
echo "$wynik"

(())

Przy odwoływaniu się do zmiennych w \((())\) nie musimy poprzedzać ich znakiem $, gdyż każdy identyfikator wewnątrz podwójnych nawiasów jest traktowany jak zmienna. Nie musimy także dbać o używanie odstępów i backslashowania znaków specjalnych. Wyrażenia arytmetyczne mogą tu zawierać dowolne operatory, które można znaleźć w języku C, np. inkrementacje/dekrementacje zmiennych (ID++, --ID), operacje bitowe \(( <<, \&, ~)\) , przypisania arytmetyczne \((=, +=, *=)\), itp.

Składni (( wyrażenie )) używamy wtedy, gdy nie potrzebujemy wyniku, czyli wtedy, gdy wyrażenie nie jest częścią instrukcji, tylko jest sama w sobie instrukcją.

x=1; y=2 # przypisanie wartości liczbowych zmiennym x i y
(( x = x+y ))  # skladnia w srodku (( )) jest podobna do skladni jezyka C
echo  x = $x
(( x++ ))
echo $((x))
y=$((x++))
echo $y $x # post inkrementacja jak w C++
y=$((++x))
echo $x $y # pre inkrementacja jak w C++
echo $((x += x > 0))
echo "1 + ... + $x = $((x * (x + 1) >> 1))"

let

Do przeprowadzenia obliczeń można też skorzystać z polecenia let.

liczba1=5
liczba2=6
let wynik=liczba1*liczba2
echo $wynik

Działania arytmetyczne

B=2
C=5
A=$((B/C))
echo $A # dzialamy na liczbach calkowitych!
echo $((B/C)) # powinno być 0.4 a jest   => 0
echo "scale=5 ; ($B/$C)" | bc  # dla wartości ułamowych musimy uzyć bc
echo "scale=15 ; ($B/$C)" | bc  #
A=$[B**2] # potęgowanie
echo $A

Instrukcja warunkowa if

Sprawdza czy warunek jest prawdziwy, jeśli tak to wykonane zostanie polecenie lub polecenia znajdujące się po słowie kluczowym then. Instrukcja kończy się słowem fi. Składnia:

if warunek then lista fi

Występujący w instrukcji warunek, od którego uzależnione jest wykonanie zestawu komend lista, to zazwyczaj wyrażenie o następującej postaci:

[[ wyrażenie_warunkowe ]]

gdzie wyrażenie_warunkowe może być jedna z niżej podanych konstrukcji:

-a fname - plik lub katalog o nazwie fname istnieje

-d fname - fname jest nazwa katalogu

-f fname - fname jest nazwa zwykłego pliku

-w fname - użytkownik ma prawo zapisu pliku fname

-x fname- użytkownik ma prawo wykonania pliku fname

napis = wzorzec - napis i wzorzec są zgodne

wyr1 -eq wyr2 - wartości wyrażeń wyr1 i wyr2 są równe; zamiast -eq można użyć: -ne (różne), -lt (mniejsze), -gt (większe), -le (mniejsze lub równe), - ge (większe lub równe)

war1 || war2- alternatywa warunków war1 i war2

war1 && war2 - koniunkcja warunków war1 i war2

!war - negacja warunku war

Innym sposobem określenia warunku jest komenda

test warunek

lub (równoważnie)

[ warunek ]

Komenda test zwraca wartość zero jeśli warunek jest spełniony, i wartość rożną od zera w przeciwnym przypadku. Jako warunku można także użyć dowolnej komendy lub listy komend - warunek będzie spełniony jeśli komenda taka zakończy się sukcesem, tj. zwróci status wyjścia równy zeru; w przeciwnym przypadku warunek nie będzie spełniony.

Utwórz w edytorze nowy plik i zapisz jako s.sh (postępuj tak samo dla każdego kolejnego przykładu skrytpu):

#!/bin/bash
if  [[ "$1" = '-h' ]]
then
        echo help
fi
if  [[ "$2" -eq 12 ]]
then
        echo dwanascie!
fi
if  [[ "$3" -lt 12 ]]
then
        echo mniej_niz_dwanascie!
fi
if  [[ -a s.sh ]]
then
        echo istnieje!
fi
if  [[ ! -f /tmp ]]
then
        echo nie_plik!
fi
if  test ! -f /tmp
then
        echo test OK!
fi
if  [ ! -f /tmp ]
then
        echo test nie_OK!
fi
exit

Uruchom skrypt

chmod +x s.sh
./s.sh
./s.sh -h 12 11

Oprócz opisanej powyżej, można użyć bardziej rozbudowanych postaci instrukcji warunkowej:

if warunek
then
        lista1
else
        lista2
fi

if  warunek1
then  lista1
        elif  warunek2
        then  lista2
                elif  warunek3
                then  lista3
                ...
        else lista
fi

Przykład:

#!/bin/bash
if  [[  -d  $1  ]]
        echo Usuwam wszystkie pliki z katalogu $1
        rm  $1/*
elif  [[  -f  $1  ]]
        echo Usuwam plik $1
        rm  $1
else
        echo  Nie znaleziono pliku ani katalogu o nazwie $1
fi
exit

Instrukcja case

Pozwala na dokonanie wyboru spośród kilku wzorców. Najpierw sprawdzana jest wartość zmiennej po słowie kluczowym case i porównywana ze wszystkimi wariantami po kolei. Musi być ona taka sama jak wzorzec do którego chcemy się odwołać. Jesli dopasowanie zakończy się sukcesem wykonane zostanie polecenie lub polecenia przypisane do danego wzorca. W przeciwnym wypadku użyte zostanie polecenie domyślne oznaczone symbolem gwiazdki: \(* )\) polecenie_domyślne. Polecenie kończy komenda esac.

Składania:

case zmienna in
        "wzorzec1") polecenie1 ;;
        "wzorzec2") polecenie2 ;;
        "wzorzec3") polecenie3 ;;
        *) polecenie_domyślne
esac

Przykład

#!/bin/bash
echo "Podaj cyfrę dnia tygodnia"
case $1 in
        "1") echo "Poniedziałek" ;;
        "2") echo "Wtorek" ;;
        "3") echo "Środa" ;;
        "4") echo "Czwartek" ;;
        "5") echo "Piątek" ;;
        "6") echo "Sobota" ;;
        "7") echo "Niedziela" ;;
        [a-Z]) echo "Podałeś znak" ;;
        *) echo "Nic nie wybrałeś"
esac

Pętle

Pętla for

Pętla for pozwala wykonać ciąg instrukcji sciśle określoną liczbę razy. Ogólna postać instrukcji jest następująca:

for zmienna in słowo1 słowo2...
do
    lista
    done

Przykład:

#!/bin/bash
for i in ala ma kota
do
        echo $i
done

echo -e "\n"

for i in "ala ma" kota
do
        echo $i
done

echo -e "\n"

# przejście po plikach o nazwie zaczynającej się na "a"

for i in a*
do
        echo $i
done

echo -e "\n"

# Jako parametr ciągu znaków po którym ma iterować zmienna można podać polecenie podane w apostrofie:

for i in `ps`
do
        echo $i
done

# Może również iterować po wartościach liczobowych:

for ((i=1;i<10;i++))
do
        echo $i
done

exit

W pętli for można również skorzystać z instrukcji break i continue

#!/bin/bash
for ((i=1;i<10;i++))
do
        if [ $i -eq 5 ]
then
        continue
elif [ $i -eq 9 ]
then
        break
else
        echo $i
fi
done
exit

Przykład 2:

#!/bin/bash

for pliki_txt in $(ls *.txt)
do
        numer=$((numer+1))
        echo "$numer. "
        echo $pliki_txt
done

echo -e "\n"

for f in *; do # * rozwija się do listy wszystkich plików/katalogów znajdujących się w bieżącym katalogu
        if [ -d "$f" ]; then
                echo "Katalog '$f'"
        elif [ -f "$f" ]; then
                echo "Plik '$f'"
        else
                echo "Inny typ '$f'"
        fi
done
exit

Przykład 3

#!/bin/bash
# Wypisywanie argumentów skryptu
n=1
for arg in "$@"; do
        echo "Argument $n: $arg"
        let "n++"
done
exit

while i until

Pozostałe dwa rodzaje pętli pozwalają na wykonanie ciągu poleceń lista w zależności od tego, czy warunek (którym może być wyrażenie warunkowe, komenda lub nawet lista komend) jest spełniony. Ogólna postać obu konstrukcji jest pokazana poniżej. W instrukcji while warunek sprawdza się na początku, i lista jest wykonywana tak długo, jak długo warunek jest spełniony. W pętli until warunek sprawdzany jest na końcu, i pętla wykonywana jest tak długo, jak długo warunek nie jest spełniony.

while warunek
do
    lista done

until warunek
do
    lista done

Przykład:

#!/bin/bash
i=5
while [ $i -gt 0 ]
do
        echo $i
        i=$((i-1))
done
x=1;
until [ $x -ge 10 ]; do
        echo "Napis pojawił się po raz: $x"
        x=$[x + 1]
done

<<

Utwórz w edytorze nowy plik i zapisz jako tr.sh :

#!/bin/sh
echo "Moje ulubione liczby:"
sort -n << LICZBY
120
10
2006
314159
0
LICZBY
echo "Od najmniejszej do największej, rzecz jasna"

Uruchom

chmod +x tr.sh
./tr.sh

extra

Takie cuda:

clear
echo -e "\033[1m Hello World"
# bold effect
echo -e "\033[5m Blink"
# blink effect
echo -e "\033[0m Hello World"
# back to noraml

echo -e "\033[31m Hello World"
# Red color
echo -e "\033[32m Hello World"
# Green color
echo -e "\033[33m Hello World"
# See remaing on screen
echo -e "\033[34m Hello World"
echo -e "\033[35m Hello World"
echo -e "\033[36m Hello World"

echo -e -n "\033[0m "
# back to noraml

echo -e "\033[41m Hello World"
echo -e "\033[42m Hello World"
echo -e "\033[43m Hello World"
echo -e "\033[44m Hello World"
echo -e "\033[45m Hello World"
echo -e "\033[46m Hello World"

echo -e "\033[0m Hello World"
# back to noraml

Zadania

  1. Napisz skrypt wyświetlający w odwrotnej kolejności argumenty jego wywołania.

  2. Napisz program wypisujący wszystkie dzielniki liczby podanej jako pierwszy argument.

  3. Napisz program obliczający średnią liczb podanych jako argumenty funkcji.

  4. Napisz skrypt sortujący zawartości wszystkich plików o rozszerzeniach wskazanych pierwszym argumentem.

  5. Sporządzić listę plików, znajdujących się w katalogu domowym, posortowanych malejąco wg numerów i–węzłów (i-węzeł pliku znajduje się w pierwszej kolumnie po wydaniu polecenia ls –i).

  6. Napisać skrypt liczący łączną liczbę słów z pierwszych trzech linii plików zaczynających się na literę p lub k.

*

Wykorzystano materiały z:

http://www.cs.put.poznan.pl/csobaniec/edu/sop/doc/sop1.pdf

https://bap.faculty.wmi.amu.edu.pl/index.php/dydaktyka/dsop/

http://dief.republika.pl/main.html

http://wazniak.mimuw.edu.pl/index.php?title=%C5%9Arodowisko_programisty/Bash_-_pisanie_skrypt%C3%B3w

http://www.ire.pw.edu.pl/~awroble/Ania_pliki/powloka_UNIX.html

http://www.kalkowski.name/dydaktyka/2012-2013-Z/DSOP/zajecia-skrypty-2/