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 $?
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
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))"
Do przeprowadzenia obliczeń można też skorzystać z polecenia let.
liczba1=5
liczba2=6
let wynik=liczba1*liczba2
echo $wynik
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
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
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ę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
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
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
Napisz skrypt wyświetlający w odwrotnej kolejności argumenty jego wywołania.
Napisz program wypisujący wszystkie dzielniki liczby podanej jako pierwszy argument.
Napisz program obliczający średnią liczb podanych jako argumenty funkcji.
Napisz skrypt sortujący zawartości wszystkich plików o rozszerzeniach wskazanych pierwszym argumentem.
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).
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/