Tartalomjegyzék
Shell programozás
- Szerző: Sallai András
- Copyright © 2011, Sallai András
- Szerkesztve: 2011-2021
- Licenc: CC BY-SA 4.0
- Web: https://szit.hu
Bevezetés
A shell programok végrehajtható parancsok gyűjteménye, vagyis egymás után írt parancsok listája egy állományban. Nevezhetjük egyszerűen shell scriptnek is.
A shell scripteknek nem kötelező kiterjesztést megadni. Ha mégis szeretnénk megadni akkor válasszuk az .sh kiterjesztést. A rendszer azonban nem a kiterjesztésből fogja eldönteni, hogy shell script vagy nem az.
Ha egy fájlba parancsokat írunk, azt shell scriptként futtatva a parancsok végrehajtódnak. A unixos rendszerekben a scripteket egy karakterpárral kezdjük:
#!
A rendszer ebből tudja, hogy valamilyen scriptről van szó. Ha egy hexa szerkesztővel nézzük:
hexedit scriptnev
Akkor azt mondhatjuk a következő kódú karakterrel kezdődik:
23 21
A unix alapú rendszerekben a futtatható fájloknak sincs kiterjesztése alapértelmezetten. A Linux például ELF binárisokat futtat. Egy ELF bináris fájl eleje mindig a következő byte sorozattal kezdődik:
7F 45 4C 46
Nézzük meg például az ls parancsunkat (Felhasználóként! Ne rendszergazdaként!).
hexedit /bin/ls
Kilépés Ctrl + C
Ha a hexedit nem lenne telepítve:
apt install hexedit
A scriptek, tehát #! kezdődnek, de honnan tudja a rendszer, hogy milyen scriptről van szó? A #! után adjuk meg az interpreter nevét és elérési útját. Perl script esetén például:
#!/usr/bin/perl
Bash shell script esetén, például:
#!/bin/bash
Python script esetén, például:
#!/usr/bin/python
Első lépések
- Szükségünk van egy szövegszerkesztőre, amiben megírjuk a scriptet.
- Futtathatóvá kell tennünk a scriptet.
- Szintaktika:
- chmod jogok script-neve
- Példa:
- chmod +x bar
- chmod 755 bar
- Futtatjuk a scriptet
- Szintaktika:
- bash script-neve
- sh script-neve
- ./script-neve
- Példa:
- $ bash bar
- $ sh bar
- $ ./bar
Megjegyzés
Az utolsó szintaktikában a ./ jelentése: az aktuális könyvtár, de csak ez.
A . (dot) karaktert használhatjuk önmagában is, ez induláskor nem hoz létre egy új shell másolatot.
Szintaktika:
. script-neve
Példa:
$ . foo
Ha egy olyan scriptet indítunk amelyik nem áll le azonnal (például vár adatbevitelre), akkor meggyőződhetünk a fentiekről ha futtatjuk a felhasználó nevén a pstree parancsot. Legyen a példa kedvéért egy joska nevű felhasználó aki a ker.sh nevű scriptet indítja. A scriptet ./ker.sh vagy . ker.sh formában indítja, ekkor lekérdezzük a folyamatfát:
pstree joska
A lehetséges kimenet ./ker.sh esetén:
bash───pstree bash───ker.sh
A lehetséges kimenet . ker.sh esetén:
bash───pstree bash
A különbséget a ps parancs is megmutatja:
ps u
Kapcsolónak csak a „u” kapcsolót kell megadni.
Azt már tudjuk, hogy egy shell sciptet mindig „#!” karakterekkel kezdjük és utána leírjuk az értelmező útvonalát. De hogyan deríthatő ki az értelmező útvonala? Mi most, Bash shell-t szeretnénk használni. A which parancs megmondja, hogy honnan fut egy parancs:
which bash
Megjegyzés
- script.sh
#!/bin/bash # egy soros megjegyzés : ' Több soros megjegyzés '
A (:) kettőspont után szóköz szükséges.
Kivitel
Hozzuk létre első „Helló Világ!” nevű shell scriptünket. készítsünk egy elso.sh nevű fájlt, melynek tartalma a következő:
- elso.sh
#!/bin/bash echo "Helló Világ!"
Adjunk rá futtatási jogot:
chmod +x elso.sh
Futtassuk:
./elso.sh
Ezek után minden további scriptünket így kell létrehoznunk.
Sorvége:
echo -n "Helló Világ!"
Utóbbi utasítás a -n hatására nem ír a sorvégére sortörést.
Escape szekvenciák
Az „Escape” karakterek engedélyezése:
echo -e "Helló Világ!"
A -e kapcsoló engedélyezi az escape karakterek értelmezését a karakterláncokban:
- \a csengő
- \b egy karakter törlése visszafelé
- \c nem ír ki újsor karaktert
- \f lapdobás
- \n új sor
- \r kocsi vissza
- \t vízszintes tabulátor
- \v függőleges tabulátor
- \\ backslash
- \0nnn a karakter ASCII kódja nnn (oktálisan)
- \xnnn a karakter ASCII kódja nnn (hexadecimálisan)
Az escape karakter a normál karakter egy speciális értelmezése. Az „a” például csengőhang, az „n” sortörés. Azt, hogy speciális escape értelmezés következik egy „\” visszaperjel karakterrel mondjuk meg. A következő parancs például a „Helló” és a „Világ!” szöveget külön sorba írja:
echo -e "Helló\nVilág!"
Változók és az értékadás
A változók kis és nagybetű érzékenyek. A SZAM és a szam változó két különböző változó. Az átláthatóság érdekében a változóneveket nagybetűvel szokás írni.
SZAM=3 SZOVEG="alma" echo $SZAM echo $SZOVEG
Az értékadó operátor előtt és után nem hagyhatunk whitespace karaktert, mert akkor a SZAM vagy SZOVEG változót egy parancsnak venné.
Változó deklaráció
#!/bin/bash declare -i szam szam=4 szam=szam+1 szam+=1 echo $szam
#!/bin/bash declare -i szam=4 szam=szam+1 szam+=1 echo $szam
Formázott kimenet
A printf utasítással a kiírt változókat, értékeket több módon formázhatjuk. Elsőként lássunk egy szimpla változó kiíratást:
printf "%s\n" $HOME
printf "%s\n" alma
printf "%d\n" 35
Szélesség megadása:
printf "%10d\n" 35
Vezető nullák:
printf "%0d\n" 35
printf "%f\n" 35,12345
Tizedesjegyek megadása:
printf "%.2f\n" 35,12345
Egyszerre több:
printf "%010.2f\n" 35,12345
A prrintf segítségével színezhetjük is a kimenetet:
printf "\033[0;32mszínes szöveg\n"
printf "\033[1;33mszínes szöveg\n"
Meg kell jegyezzem, az echo parancs a -e kapcsolóval értelmezi az escape szekvenciákat, és ugyanez a hatás elérhető:
echo -e "\033[1;33mszínes szöveg\n"
Unicode karakter kiíratása is lehetséges a \U escape szekvenciával. Lássuk az „üres” szót:
printf "%b" "Unicode Character (U+7a7a) \U7a7a \n"
A „U” nagy u helyett használhatunk „u” kis u-t is.
Leghosszabb kiírható számjegy: 1234567890123456789
Formátumkód | Leírás |
---|---|
d | Egész szám kiíratás |
f | Valós szám kiíratás |
s | String kiíratás |
Jelző | Leírás |
---|---|
0 | vezető nullák |
- | balra igazítás |
+ | előjel |
Véletlen generálás
Véletlen szám
Az alábbiakban többféle véletlen szám előállítási lehetőséget ismerhetünk meg.
echo $RANDOM
n=$RANDOM echo $n
1 és 3 között egy szám:
echo $((RANDOM % 3 + 1))
0 és 4 közötti számot véletlenszerűen:
r=$RANDOM R=$((r %= 5)) echo $R
0 és 4 közötti szám:
echo $(( $(od -An -N2 -i /dev/random) % 5))
Véletlenszám az od paranccsal:
od -A n -N 1 -t d < /dev/urandom
A -t d decimális formában kiírásról gondoskodik. A -N 1, egyetlen bájt vételét írja elő.
shuf -i 1-10 -n 1
Ha telepítve van a perl nyelv:
perl -e 'print int rand 10, "\n"; '
Véletlen bemenet
A shuf a bemenetére kapott sorokból véletlenszerűen választ, majd kiírja a kimenetre:
echo -e "1\n2\n3\n4\n5" | shuf -n 1
könyvtár tartalmából véletlenszerűen választás:
ls dir1 | shuf -n 1
Kifejezés kiértékelése
expr 1 + 3
Az 1+3 összegét, azaz 4-et ad vissza
- script.sh
#!/bin/bash A=3 B=7 expr $A + $B
- script.sh
#!/bin/bash A=3 B=7 C=`expr $A + $B` echo $C
- script.sh
#!/bin/bash A=3 B=7 C=`expr $A "*" $B` echo $C
- script.sh
#!/bin/bash A=3 B=7 C=`expr \( $A "*" $B \) / 2 ` echo $C
- script.sh
#!/bin/bash A=3 B=7 C=`echo \( $A "*" $B \) / 2 | bc` echo $C
Gyökvonás:
- script.sh
#!/bin/bash echo sqrt\(9\) | bc
Hatványozás:
- script.sh
#!/bin/bash echo 2 ^ 8 | bc
Dupla zárójel
A következő program a szam változó értéket 1-gyel növeli:
- szamol.sh
#!/bin/bash szam=3 szam=$((szam+1)) echo $szam
Variációkat láthatunk a növelésre:
szam=$((szam+1)) ((szam=szam+1)) ((szam+=1)) ((szam++))
A let kulcsszó használata
#!/bin/bash szam=3 let "szam=szam+1" echo $szam
Variációk a let kulcsszó használatára:
let "szam=szam+1" let "szam+=1" let "szam++" let szam=szam+1 let szam+=1 let szam++
A bc
#!/bin/bash declare -i szam=4 bc <<< "$szam+2"
#!/bin/bash declare -i szam=4 echo "$szam+2" | bc
Bevitel
Ebben a részben megnézzük, hogyan kérhetünk be a billentyűzetről értékeket.
echo -n "Szó: " read SZOVEG
Egy szöveg bekérése a SZOVEG változóba. A bekérést a read utasítás végzi. Az előtte lévő echo utasítás jelzi a „Szó: ” képernyőre való írásával, hogy egy szó begépelését várjuk. Az echo -n kapcsolója a „Szó: ” szöveg után nem ír sortörést. Így a bekérés rögtön a kettőspont-szóköz után lehetséges.
Bekérés echo nélkül:
- script.sh
#!/bin/bash read -p "Felhasználónév: " USER echo "A felhasználónév: "$USER
A bekérés szövegét echo nélkül is kitudjuk íratni a read -p kapcsolója segítségével.
Beolvasás tömbbe:
- script.sh
#!/bin/bash echo -n "Gyümülcsök: " read -a GYUMOLCSOK echo ${GYUMOLCSOK[0]} echo ${GYUMOLCSOK[1]}
A read utasítás a -a kapcsoló hatására indexelt tömbváltozót hoz létre. Lásd „help read”.
A beolvasandó értékeket szóközzel tagolva adjuk meg. Például:
Gyümölcsök: körte alma barack szilva
Jelszó beolvasása:
- script.sh
#!/bin/bash echo -n "Jelszó: " read -s JELSZO echo echo "A beírt jelszó: " $JELSZO
- script.sh
#!/bin/bash read -p "Jelszó: " -s JELSZO echo echo "A beírt jelszó: " $JELSZO
Alapértelmezett szöveg megadása:
- script.sh
#!/bin/bash read -e -i "joska" -p "Felhasználónév: " USER echo "A beírt felhasználónév: "$USER
A „-e” kapcsoló is szükséges.
Szelekció
if
#!/bin/bash SZAM=2 if [ $SZAM -eq 2 ] then echo "Egyenlo" else echo "Negy egyenlo" fi
Az -eq egyenlőséget vizsgál. Használható még a „=” vagy a „==” karakterek is, viszont ezen operátorok előtt és után kötelező egy vagy több whitespace karakter.
#!/bin/bash SZAM=2 if [ $SZAM -ne 2 ] then echo "Nem egyenlő kettővel" else echo "Egyenlő kettővel" fi
A -ne azt jelenti nem egyenlő. Használható helyette a != alak is.
#!/bin/bash SZAM=2 if [ $SZAM -gt 2 ] then echo "Nagyobb" else echo "Kisebb vagy egyenlő mint kettő" fi
#!/bin/bash SZAM=2 if [ $SZAM -lt 2 ] then echo "Kisebb mint kettő" else echo "Nagyobb vagy egyenlő mint kettő" fi
#!/bin/bash SZAM=2 if [ $SZAM -le 2 ] then echo "Kisebb vagy egyenlő mint kettő" else echo "Nagyobb mint kettő" fi
#!/bin/bash SZAM=2 if [ $SZAM -ge 2 ] then echo "Nagyobb vagy egyenlő" else echo "Kisebb" fi
elif
#!/bin/bash read -p "Gyümölcs: " fruit if [ "$fruit" = "alma" ]; then echo "Ez alma" elif [ "$fruit" = "körte" ]; then echo "Ez körte" else echo "Nem alma és nem körte" fi
select
- valaszt.sh
#!/bin/bash select i in "egy" "kettő" "három" do echo Ezt választottad: echo $i done
Kiírja az „egy”, „kettő”, „három” szavakat sorszámokkal bevezetve. Valójában egy ciklus is elindul. Mindig várja, hogy válasszunk egyet. A ciklus a Ctrl + C billentyűkombinációval is.
A ciklus persze megszakítható a break utasítással a cikluson belülről is.
- valaszt.sh
#!/bin/bash select i in "egy" "kettő" "három" "kilépés" do echo Ezt választottad: echo $i if [[ "$i" = "kilépés" ]] ; then break fi done
És, vagy logikai operátorok
Több feltétel is megadható, ha megduplázzuk a szögletes zárójeleket:
if [[ $num -eq 3 && "$str" == foo ]] then # Utasítások fi
Vagy:
- script.sh
#!/bin/bash A=0 B=1 if [[ $A -eq 1 || $B -eq 1 ]] then echo "Ok" else echo "Nem ok" fi
És:
- script.sh
#!/bin/bash A=0 B=1 if [[ $A -eq 1 && $B -eq 1 ]] then echo "Ok" else echo "Nem ok" fi
Kevert:
- script.sh
#!/bin/bash A=1 B=0 C=1 if [[ ($A -eq 1 || $B -eq 1) && $C -eq 1 ]] then echo "Ok" else echo "Nem ok" fi
Szelekció másként
Szimpla szelekció
#!/bin/bash A=1 [ $A -eq 1 ] && echo "Ok" || echo "Nem ok"
Vagy logikai operátor
#!/bin/bash A=1 B=1 [ $A -eq 1 ] && [ $B -eq 1 ] && echo "Ok" || echo "Nem ok"
És logikai operátor
#!/bin/bash A=1 B=1 [ $A -eq 1 ] && [ $B -eq 1 ] && echo "Ok" || echo "Nem ok"
Vegyes logikai operátorok
#!/bin/bash A=1 B=1 C=0 ([ $A -eq 1 ] || [ $B -eq 1 ]) && [ $C -eq 1 ] && echo "Ok" || echo "Nem ok"
Több ágú elágazás
echo "[O]lvas" echo "[H]ozzáfűz" echo "[S]zerkeszt" read menupont case "$menupont" in "O" | "o" ) echo "Olvasási műveletek" ;; "H" | "h" ) echo "Hozzáfűzési műveletek" ;; "S" | "s" ) echo "Szerkesztési műveletek" ;; esac
Iteráció
for
Számok 1-től - 10-ig, variációk:
for i in `seq 1 10` do echo $i done
for i in `seq 1 10`; do echo $i ; done
for i in 1 2 3 4 5 6 7 8 9 10 do echo $i done
Egy könyvtár tartalmát végig vesszük:
for i in `ls /etc` do echo $i done
A példában listázzuk az /etc könyvtár tartalmát.
Zip fájlok feldolgozása:
#!/bin/bash for file in * do if [[ "$file" = *.zip* ]] then echo "$file" fi done
#!/bin/bash for (( i=0; i<10; i++ )) do echo "Helló" done
#!/bin/bash for (( i=0; i<10; i++ )) do echo $i done
while
Amíg típusú ciklus (while)
#!/bin/bash SZAMLALO=1 while [ $SZAMLALO -lt 11 ] do echo $SZAMLALO let SZAMLALO=SZAMLALO+1 done
Számok bekérése nulla végjelig:
#!/bin/bash SZAM=1 while [ $SZAM -ne 0 ] do echo -n "Szám: " read SZAM done
Számok bekérése nulla végjelig, közben összegzés.
#!/bin/bash SZAM=1 SZUM=0 while [ $SZAM -ne 0 ] do echo -n "Szám: " read SZAM let SZUM=$SZUM+$SZAM done echo "Összeg: " $SZUM
A let nélkül sztringkét adja össze.
Végtelen ciklus létrehozása:
while true do #amit csinálunk a végtelen ciklusban done
Másik módszer a végtelen ciklusra:
while : do #amit csinálunk a végtelen ciklusban done
while : do echo -n "Számot: " read SZAM if [ $SZAM -lt 1 ] then exit 0 fi done
Fájl olvasása
- script.sh
#!/bin/bash while read sor do echo $sor done < gy.txt
- script.sh
#!/bin/bash cat gy.txt | while read sor do echo $sor done
Könyvtár tartalmának olvasása
A .txt kiterjesztésű fájlok olvasása:
- script.sh
#!/bin/bash DIR=konyvtar/alkonyvtar cd $DIR find $DIR -name '*.txt' | while read sor do echo $sor done
until
#!/bin/bash SZAMLALO=1 until [ $SZAMLALO -gt 10 ] do echo $SZAMLALO let SZAMLALO=SZAMLALO+1 done
Tömbök
Üres tömb:
tomb=()
Kezdőértéket zárójelek között adhatunk:
tomb=( "egy" "kettő" "három")
A Bash tömb tartalmazhat számokat és karakterláncokat is:
tomb=( 12 "egy" 45 29 "kettő" "három")
Hivatkozás egy tömbelemre:
echo ${tomb[1]}
Ez a második elemet adja vissza, vagyis az indexelés 0-val kezdődik.
A tömb elemei így is felvehetők:
tomb[0]=egy tomb[1]=kettő tomb[2]=három echo ${tomb[1]}
A tömb tulajdonságai
#!/bin/bash #Összes elem: echo ${tomb[*]} echo ${tomb[@]} #Összes index: echo ${!tomb[*]} echo ${!tomb[@]} # Elemek száma: echo ${#tomb[*]} echo ${#tomb[@]} echo ${#tomb[0]} # a 0-dik elem hossza
A tömb bejárása
#!/bin/bash ketogenEtelek=( "Halsaláta" "Zöldségkör" "Húsleves" "Narancs-joghurt" ) for item in ${ketogenEtelek[*]} do echo $item done
A tömb bejárása a for in szerkezettel, csak akkor működik, ha nincs szóköz a tömb elemeiben. Ha a tömb elemei szóközöket is tartalmaznak, akkor a következő ciklus alkalmas bejárásra:
A „*” karakter helyett használhatunk „@” karaktert is.
Szimpla for ciklus használata:
#!/bin/bash etelek=( "Halsaláta (uborka, tonhal, tejföl)" "Zöldségkör (tejföl, túró, zöldségek)" "Húsleves" "Narancs joghurt" ) n=${#etelek[@]} for (( i=0; i<n; i++)) do echo ${ketogenEtelek[$i]} done
Tömb műveletek
Hozzáfűzés
dobasok=(1 5 4) dobasok+=(7 8) echo ${dobasok[@]}
Ürítés:
dobasok=()
Tömb része:
echo ${tomb[@]:2:3}
A 2-s indextől szeretnénk, 3 darab karaktert.
Elem törlése:
tomb=(33 49 56 27) unset tomb[1] echo ${tomb[@]}
Ha ezek után kiíratjuk a tömb indexeit, ezt kapjuk:
echo ${!tomb[@]} 0 2 3
Hiányzik a 1-s index.
Egész tömb törlése:
unset tomb
Deklarált tömb
Indexelt tömb:
declare -a szamok
Asszociatív tömb:
declare -A tomb
Indexelt tömb feltöltéssel:
declare -a szamok szamok+=35 szamok+=47
Asszociatív tömbnek értékadás:
declare -A dolgozo #egy érék hozzáadása: dolgozo[fizetes]=3800000 #több érték hozzáadása: dolgozo=([nev]=János [telepules]=Szolnok) echo ${dolgozo[nev]}
String
Hossz
SZOVEG="Nagy János" meret=${#SZOVEG} echo $meret
SZOVEG="abc123" HOSSZ=$(printf "%s" "$SZOVEG" | wc -c)
echo ${#SZOVEG} echo -n $SZOVEG | wc -m echo -n $SZOVEG | wc -c printf $SZOVEG | wc -m expr length $SZOVEG expr $SZOVEG : '.*'
Kisbetű, nagybetű
STR="Alma" echo $STR # alma echo ${STR,,} # alma echo ${STR^^} # ALMA
A fenti megoldás, csak a 4.x Bash verziótól működik.
Használhatjuk a tr parancsot, ami viszont nem viszi a magyar ékezetes karaktereket.
STR="Alma" echo "$STR" | tr '[:upper:]' '[:lower:]'
Megoldás lehet még az awk használata:
echo "ÁRVÍZTŰRŐ" | awk '{print tolower($0)}'
echo "Árvíztűrő" | awk '{print toupper($0)}'
A Bash megoldás esetén használhatunk egyetlen ^ vagy , karaktert. Ekkor csak az első karakterre vonatkozik a beállítás.
STR=árvíztűrő; echo ${STR^} Árvíztűrő
Milyen betűk legyenek nagybetűk:
STR=árvíztűrő; echo ${STR^^[v,z]} árVíZtűrő
Ékezetlenítés
Repülő ékezetek, normál ékezet helyett:
echo árvíztűrő | iconv -f UTF-8 -t ASCII//TRANSLIT
# apt install unaccent
$ echo árvíztűrő | unaccent utf-8 arvizturo
$ echo árvíztűrő | sed 'y/áíéóöőúüű/aieooouuu/'
Tartalmaz-e?
#!/bin/bash if [[ $a == *"é"* ]] then echo "Van benne é betű" else echo "Nincs benne é betű" fi
String bejárása karakterenként
#!/bin/bash a=béla for (( i=0; i<${#a}; i++ )) do echo "${a:$i:1}" done
Regex
Az [a-z] mint megfelel az angol ábécé betűinek plusz áíóöúü betűknek, de nem felel meg a ő és ű betűknek.
#!/bin/bash a=belí if [[ $a =~ ^[a-z]+$ ]] then echo "Megfelel" else echo "Nem felel meg" fi
String darabolása
- darabol.sh
#!/bin/bash str="alma:körte:barack:szilva" IFS=':' read -ra tomb <<< "$str" echo ${tomb[0]}
Heredoc szintaxis
- naplo.sh
#!/bin/bash date=$(date "+%Y-%m-%d") cat << EOT ========== $date Óra: Téma: Hiányzók: 1 óra: 2 óra: 3 óra: Dolgozat: Hetes: EOT
Üres sorok törlése
cat fajl.txt | sed '/^$/d'
Adott karakterek törlése
A következő karakterek törlése:
. ? - , |
cat fajl.txt | sed '/[\.?-\,]//g'
Visszatérési érték
Vizsgáljunk meg egy program végrehajtásának sikerességét. A példában az smbmount parancsot vizsgáljuk a végrehajtás sikerességéről.
#!/bin/bash smbmount //server/megosztasnev -o username=joe,password=titok,uid=joe,gid=csoport if [ $? == 0 ] then echo echo "A végrehajtás sikeres" echo else echo echo "Hiba a végrehajtás során" echo fi
Karaktersorozat vizsgálatok
Operátorok:
= | egyenlő |
!= | nem egyenlő |
< | rövidebb |
> | hosszabb |
-z $NEV | a NEV üres |
#!/bin/bash ELSO="Kati" MASODIK="Kati" if [ $ELSO = $MASODIK ] then echo Egyezik else echo Nem egyezik fi
Üres vagy nem üres a string:
#!/bin/bash ELSO="" if [ -z $ELSO ] then echo Üres else echo Nem üres fi
Az ASCII táblában előrébb vagy hátrább van-e:
#!/bin/bash ELSO="szilva" MASODIK="zalma" if [ $ELSO \> $MASODIK ] then echo "Hátrébb van" else echo "Előrébb van" fi
vagy így:
#!/bin/bash ELSO="szilva" MASODIK="zalma" if [[ $ELSO > $MASODIK ]] then echo "Hátrébb van" else echo "Előrébb van" fi
#!/bin/bash ELSO="s*" # minta egyezés if [[ $ELSO == s* ]] then echo "s-el kezdődik" else echo "Nem s-el kezdődik" fi
#!/bin/bash ELSO="s*" # literális egyezés if [[ $ELSO == "s*" ]] then echo "s* van benne" else echo "Nem s* van benne" fi
#!/bin/bash ELSO="s*" # literális egyezés if [ "$ELSO" == "s*" ] then echo "s* van benne" else echo "Nem s* van benne" fi
Függvények, eljárás használata
Függvény:
- minta.sh
function kiir() { echo "Helló Világ" } kiir
Függvény paraméterrel:
- minta.sh
function kiir() { echo $1 } kiir "Ezt írd ki"
Bemenő paraméter és visszatérési érték:
- fg.sh
#! /bin/bash function dupla() { local res=$(echo "$1 * 2" | bc) echo "$res" } result=$(dupla 3) echo $result
Ez a megoldás is működik, de az előbbi korrektebb:
- vissza.sh
#! /bin/bash function dupla() { res=$(echo "$1 * 2" | bc) } dupla 3 echo $res
Példa:
#!/bin/bash # Rekurzívan az alkönyvtárakban is átnevez minden fájlt kisbetűsre # Jelenleg csak fájlokra működik, könyvtárakra nem. # Latin2-es környezetben működik (1 karakter == 1 byte), UTF-8-ban nem. # UTF-8-as környezetben a tr helyett a sed parancsot használjuk! function files() { for i in * ; do if [ -f "$i" ]; then j=`echo "$i" | tr '[:upper:]' '[:lower:]'` if [ "$i" != "$j" ]; then mv -i "$i" "$j" fi fi done } function dirs() { for i in *; do if [ -d "$i" ]; then cd "$i" dirs files cd .. fi done } dirs files
Tömbök
Tömb visszatérési érték:
function leker_tomb() { tomb=(9 4 2 5) echo ${tomb[@]} } a_tomb=($(leker_tomb)) echo "Összes elem: "${tomb[@]} echo "Mérete: "${#tomb[@]}
Változók hatásköre
A következő script szemlélteti a változók hatáskörét. A local kulcsóval létrehozott függvényen belüli változó nem látszik csak a függvényben. Az $ERO nevű változó viszont globális, mindenhol látszik.
#!/bin/bash ERO="85" function csokkent { local MERTEK=5 echo "Erő csökkentése..." ERO=`expr $ERO - $MERTEK` } echo "Erő: $ERO" csokkent echo "Erő csökkentés után: $ERO" echo "Csökkentés mértéke: $MERTEK"
Külső változó felhasználása:
#!/bin/bash szam=45 function csinal() { szam=100 echo "Működik" } csinal echo "$e"
Fájl és könyvtár tesztek
Használható kapcsolók listája
- -b filename A fájl speciális blokk?
- -c filename A fájl speciális karakterfájl?
- -d directoryname A könyvtár létezik?
- -e filename A fájl létezik?
- -f filename A fájl általános fájl, nem egy könyvtár?
- -G filename Ha a fájl létezik, érvényes tulajdonos érvényes csoportazonosító?
- -g filename true ha fájl létezik és van set-group-id
- -k filename Sticky bit
- -L filename Szimbolikus link
- -O filename True ha fájl létezik és az felhasználó érvényes azonosító.
- -r filename Ellenőrzés, ha a fájl olvasható.
- -S filename Ellenőrzés, ha a fájl socket
- -s filename Ellenőrzés, ha a fájl nem nonzero méretű
- -u filename Ellenőrzés, ha set-ser-id bit be van állítva
- -w filename A fájl írhatóságának ellenőrzés
- -x filename A fájl futtathatóságának olvasása
A fájl létezésének ellenőrzése
#!/bin/bash file="adat.txt" if [ -e $file ]; then echo "A fájl létezik" else echo "A fájl nem létezik" fi
Első paraméter létezésének vizsgálata
#!/bin/bash if [ -z "$1" ]; then echo usage: $0 directory exit fi
Könyvtár vizsgálat
Példa a könyvtárvizsgálatra:
if [ -d "$DIRECTORY" ]; then # Mit tegyünk, ha a $DIRECTORY könyvtár létezik fi
A könyvtár neve (esetleg útvonala) a $DIRECTORY változóban találjuk.
Ha a könyvtár nem létezik:
if [ ! -d "$DIRECTORY" ]; then # Mit tegyünk, ha a $DIRECTORY nem létezik fi
Parancs kimenete
[ -z "`ls`" ] && echo "Nincs fájl"
A [ -z az ls által visszaadott sztring hosszát vizsgálja, hogy az 0 értékű-e.
[ -n "`ls`" ] && echo "Van valamilyen fájl"
A [ -n az ls által visszaadott sztring hosszát vizsgálja, hogy az nagyobb-e mint 0.
Tesztek a test paranccsal
Az if utasítást után a test parancs is használható feltételek meghatározására. A következőkben erre látunk példát.
test <KIFEJEZÉS>
[ <KIFEJEZÉS> ]
A két utasítás visszatérhet 0-val (TRUE) vagy 1 (FALSE) értékekkel.
#!/bin/bash if test -e /etc/group then echo "A csoportfájl létezik..." >&2 else echo "Valami nem kerek!" >&2 exit 1 fi
A test utasítás után a kifejezés egy -e kapcsolóval kezdődik. Azt mondja egy fájl létezését akarjuk tesztelni. Ez után következik, hogy melyik fájlt szeretnénk tesztelni.
A fenti utasításnak teljesen megfelel a „[” karakter. Ha megnézzük az /usr/bin könyvtárat, akkor találni fogunk ott egy ilyen futtatható programot.
#!/bin/bash if [ -e /etc/group ] then echo "A csoportfájl létezik..." >&2 else echo "Valami nem kerek!" >&2 exit 1 fi
Beépített változók
$0 | A script neve |
$1 | paramét1 |
$2 | paramét2 |
$3 | paramét3 |
$4 | paramét4 |
$5 | paramét5 |
$6 | paramét6 |
$7 | paramét7 |
$8 | paramét8 |
$9 | paramét9 |
$# | argumentumok száma |
$@ | az összes argumentum |
$? | az utolsó folyamat kilépési kódja |
$LINENO | a script aktuális sora |
$HOSTNAME | hol fut a script |
$USER | a scriptet futtató felhasználó |
$SECONDS | a futtatás kezdete óta eltelt idő |
$RANDOM | minden hivatkozáskor más véletlen számot ad |
Fájlok, könyvtárak neveinek kezelése
A következő példákban egy könyvtárban található fájlok vagy alkönyvtárak tartalma helyett, azok nevein hajtunk végre valamit. Jelenleg csak kiíratjuk a nevüket.
- olvas.sh
#!/bin/bash FAJLOK='*.txt' ls $FAJLOK | while read next_file do echo $next_file done
- olvas.sh
#!/bin/bash DIR=/home/utvonal cd $DIR for FILE in * do echo Könyvtárnevek: $FILE done
- olvas.sh
#!/bin/bash DIR=/home/utvonal cd $DIR find $DIR -name '*.txt' | while read filename do echo $filename done
Fájlok tartalmának kezelése
A következő példa bemutatja hogyan tudjuk olvasni egy fájl tartalmát.
while read sor do echo $sor done < gy.txt
Ebben a példában is egy fájl tartalmát olvassuk, kicsit másként.
cat gy.txt | while read sor do echo $sor done
Backup
Egyszerű archiválás:
#!/bin/bash tar -czf joskadokuarchiv.tar.gz /home/joska/doku
Egy összetettebb archiváló:
#!/bin/bash DATUM=$(date +%Y%m%d) MENTENDO=/home/andras/bin KIMENET=mentes-joskahome_$DATUM.tar.gz tar -czf $KIMENET $MENTENDO
Paraméterek használata
#!/bin/bash if [ "$#" == "0" ] then echo "Használat: ./parosit.sh Név1 Név2" exit fi echo "Ennyi nevet írtál: $#" echo $1 és $2 jó választás együtt echo "A paramétereid: $@"
Szignálok elkapása (trap)
A trap paranccsal szignálokat kaphatunk el. Ha valaki megnyomja például a Ctrl + C, akkor a script befejezése előtt még tehetek valami a „csinald” nevű függvényben. Persze tetszőleges függvény írható a helyére.
#!/bin/bash trap csinald INT csinald() { echo Valaki megnyomta a Ctrl + C! Nem kéne } sleep 5
Temp fájlok
$ mktemp vmi.XXX vmi.YzM
A program kiírja milyen fájlt hoz létre. Az X-ek heléyre véletlen karaktereket helyettesít a program.
Lehet hosszabb is:
mktemp vmi.XXXXXXXX
A következő módon kinyerhető a fájl neve:
TEMP=$(mktemp vmi.XXX)
Ezek után így használjuk:
TEMP=$(mktemp /tmp/temporary-file.XXXXXXXX) echo valami > ${TEMP}
Naplózás
Ha szeretnénk, hogy a script a /var/log könyvtárba nalózzon, akkor hozzunk ott létre a script számára egy könyvtárat:
# mkdir /var/log/sajatScriptNev
Naplózás a /var/log/syslog fájlba is történhet a logger nevű parancs segítségével:
logger uzenet
Megadható a script neve is:
logger –t ScriptNev “Helló Világ”
Függelék
Futtatható fájlok
A futtatható fájlok miről ismerjük fel, itt vannak megadva:
/proc/sys/fs/binfmt_misc
Telepítés
apt-get -y install mc >/dev/null 2>&1
aptitude -y install mc >/dev/null 2>&1
Aktuális könyvtár
Parancssorból az aktuális könyvtárnév, útvonal nélkül:
basename $PWD
Másik lehetőség:
echo ${PWD##*/}
Esetleg így:
ACTDIR=$(basname $(pwd)) echo $ACTDIR
Példák
Másolás időbélyeg alapján
Legrégebbi fájl másolása:
- script.sh
#!/bin/bash cd /útvonal/könyvtár cp `ls -t1 *.txt | tail -1` /másik/útvonal/könyvtár/
Legújabb fájl mozgatása:
- script.sh
#!/bin/bash cd /útvonal/könyvtár cp `ls -t1 *.txt | head -1` /másik/útvonal/könyvtár/
Feltöltés FTP-re
- fel.sh
cd /útvonal/könyvtár wput ./ ftp://felhasználónév:jelszó@url/könyvtár/
- fel2.sh
#!/bin/sh USERNAME=jozsi PASSWORD=titok HOST_NAME=localhost LOG=naplo.txt BATCH=id_batchfile echo "user $USERNAME $PASSWORD" > $BATCH echo "bin" >> $BATCH echo "send egy.txt" >> $BATCH echo "send ketto.txt" >> $BATCH echo "exit" >> $BATCH ftp -n -v $HOST_NAME < $BATCH > $LOG rm $BATCH
- fel3.sh
#!/bin/sh USERNAME=jozsi PASSWORD=titok HOST_NAME=localhost LOG=naplo.txt ftp -n -v $HOST_NAME > $LOG <<EOF quote user $USERNAME quote pass $PASSWORD bin send egy.txt send ketto.txt exit EOF
- fel4.sh
#!/bin/sh USERNAME=jozsi PASSWORD=titok HOST_NAME=localhost LOG=naplo.txt ftp -n -i -v $HOST_NAME > $LOG <<EOF user $USERNAME $PASSWORD bin send egy.txt send ketto.txt exit EOF
Így bekéri a jelszót
- fel5.sh
#!/bin/sh USERNAME=jozsi HOST_NAME=localhost LOG=naplo.txt ftp -n -i -v $HOST_NAME > $LOG <<EOF user $USERNAME password bin send egy.txt send ketto.txt exit EOF
- fel6.sh
#!/bin/sh USERNAME=jozsi PASSWORD=titok HOST_NAME=localhost LOG=naplo.txt ftp -n -i -v > $LOG <<EOF open $HOST_NAME user $USERNAME $PASSWORD bin send egy.txt send ketto.txt exit EOF
Kicsit más:
- fel7.sh
#!/bin/sh USERNAME=jozsi PASSWORD=titok HOST_NAME=localhost LOG=naplo.txt ftp -n -v $HOST_NAME <<EOF >> $LOG 2>&1 quote user $USERNAME quote pass $PASSWORD bin prompt off mput *.txt exit EOF
Dátum
Dátum darabolása
- datum.sh
#!/bin/bash read Y m d H M <<<$(date "+%Y %m %d %H %M") echo Az év: $Y echo A hónap: $m echo A nap: $d echo Az óra: $H echo A perc: $M
Naplófájl figyelése
- figyel.sh
STR=elnok tail -f /var/log/syslog | while read -r sor do [[ "$sor" != *$STR* ]] && continue echo "Volt bejegyzés" done exit
Visszaszámlálás
A script használja az espeak programot. Ha nincs telepítve:
apt-get install espeak
Kimondva:
- visszaSzamolKimondva.sh
for i in {"öt", "négy", "három", "kettő", "egy", "zéró"};do espeak -vhu "$i" && sleep 0.5; done
Ugyanaz kiírva:
- visszaSzamolKiirva.sh
for i in {5..1};do echo -n "$i. " && sleep 1; done
Lejárt műszakik figyelése
Egy fájlban tároljuk melyik járműnek mikor jár le a műszakija. Egy scripttel pedig időnként, például időzítve ellenőrizzük, és hangosan kimondatjuk, ha körülbelül 2 hónap van a műszaki lejártáig.
- vehicles.txt
Rendszám:Műszaki lejár:Szükséges figyelmeztetés:Gyártmány:Egyéb ABC-123:2018-08-22:igen:Lada:Nincs ABD-123:2018-08-22:igen:Lada:Nincs BBC-623:2016-04-22::Lada:Nincs CAC-523:2018-02-22:igen:Lada:Nincs ABK-423:2012-04-22:igen:Lada:Nincs AKG-123:2016-05-22:igen:Lada:Nincs GBC-123:2015-08-22:igen:Lada:Nincs
- checkVehicle.sh
#!/bin/bash FILE=vehicles.txt # DEBUG-hoz: FIXDATE=2016-03-03 DATE=`date "+%Y-%m-%d"` echo $DATE HANYHONAPPAL_ELORE=2 function checkVehicle() { sor=$1 LEJAR=`echo $sor | awk -F: '{print $2}'` LEJAR_EV=`echo $LEJAR | awk -F- '{print $1}'` AKTUA_EV=`echo $DATE | awk -F- '{print $1}'` if [[ "$LEJAR_EV" == "$AKTUA_EV" ]] then LEJAR_HO=`echo $LEJAR | awk -F- '{print $2}'` AKTUA_HO=`echo $DATE | awk -F- '{print $2}'` TEMP_HO=`expr $LEJAR_HO - $AKTUA_HO` if [[ $TEMP_HO -le $HANYHONAPPAL_ELORE ]] then LEJAR_RENDSZAM=`echo $sor | awk -F: '{print $1}'` espeak -vhu "Filgyelem! Lejáró műszaki." espeak -vhu "A $LEJAR_RENDSZAM rendszámú gépjármű műszakija ekkor lejár: $LEJAR" fi fi } cat $FILE | while read sor do ERTESITES=`echo $sor | awk -F: '{print $3}'` if [[ "$ERTESITES" == "igen" ]] then checkVehicle $sor fi done
A set parancs
Sikertelen parancs esetén kilépés:
#!/bin/bash # Ha végrehajtás sikertelen a scriptben, akkor azonnal lépjen ki: set -e # Ha az aaaaa fájl nem létezik, akkor kilép. # Ha nincs set -e, akkor még kiírja a Valami szöveget is. ls aaaaa echo Valami
Próbáljuk meg a scriptet végrehajtani set -e használata nélkül is.
Zónafájl felvétele
A Debian GNU/Linux rendszeren a bind démon számára a zónákat a következő helyen kell beállítani:
- /etc/bind/named.conf.local
Ezek után egy zónafájlt kell készíteni ebbe a könyvtárba:
- /var/cache/bind/master
Ezt fogjuk automatizálni:
- zoneAdd.sh
#!/bin/bash CONFIG=/etc/bind/named.conf.local MZONES=/var/cache/bind/master echo -n "Tartománynév: " read DOMAIN echo -n "IP cím: " read IP ZONEFILE=$DOMAIN.zone cat << EOT >> $CONFIG zone "$DOMAIN" in { type master; file "master/$ZONE"; }; EOT cat << EOT >> $MZONES/$ZONEFILE \$TTL 3D @ SOA $DOMAIN. hostmaster.$DOMAIN. ( 2017111701 8H 2H 4W 2H) $DOMAIN. NS $DOMAIN. $DOMAIN. A $IP EOT
Kártyalapok kiíratása
- lapok.sh
#!/bin/bash function lap() { x=$1 y=$2 f="\u2660" # pikk tput cup $y $x echo -e "\u250c\u2500\u2500\u2510" tput cup $((y+1)) $x echo -e "\u25026$f\u2502" tput cup $((y+2)) $x echo -e "\u2514\u2500\u2500\u2518" } clear lap 5 5 lap 10 5
Az eredmény:
┌──┐ ┌──┐ │6♠│ │6♠│ └──┘ └──┘
A vonalak:
u2550 u252c u250c ┌ ─ ┬ ┐ u2510 u2502 │ u251c ├ ┼ u253c ┤ u2524 u2514 └ ┴ ┘ u2518 u2534
- treff (♣) – u2663
- káró (♦) – u2666
- kőr (♥) – u2665
- pikk (♠) – u2660
- További unicode: https://unicode-table.com/hu/
Külső linkek
- http://tldp.org/LDP/abs/html/ (Advanced Bash-Scripting Guide; 2018)
- http://wiki.koczka.hu/index.php/Kezd%C5%91lap (Operációs rendszerek; 2018)
- http://wiki.bash-hackers.org (2018)
- http://www.linuxjournal.com/article/2807 (dialog parancs; 2018)
- http://hup.hu/node/111049 (Hasznos fórum téma; 2018)