Curs 06 - Automatizarea sarcinilor. Shell scripting

Demo

Ce este un script?

Un script shell este un program scris într-un fișier text format din combinații de comenzi și instrucțiuni specifice unui interepretor de comenzi (unui shell). Shell-ul este un interpretor de comenzi care faciliteaza accesul utilizatorului la resursele sistemului de operare.

Cum arată un script shell:

#!/bin/bash
echo Noi suntem banul si stema
  • Ce înseamnă #!/bin/bash?

Secvența de caractere (shebang) care este prezentă tot timpul la începutul unui script și care indică interpretorul scriptului (în exemplul dat fiind shell-ul Bash).

  • Cum creăm și rulăm un script?

Putem deschide command line-ul, creăm un fișier cu extensia .sh (good practice), pe care ulterior îl edităm folosind orice editor text (vim, Sublime etc.), căruia ulterior trebuie sa îi dăm drepturi de execuție (chmod pentru a schimba și ls -l pentru verificare). La sfârșit, putem rula script-ul ca pe orice executabil.

student@uso:~/Documents$ vi script.sh
student@uso:~/Documents$ chmod +x script.sh
student@uso:~/Documents$ ls -l script.sh
-rwxr-xr-x 1 student student 44 nov  3 17:06 script.sh  
student@uso:~/Documents$ ./script.sh
Noi suntem banul si stema
  • De ce shell scripting?

Script-urile oferă posibilitatea de automatizare a sarcinilor putând utiliza o serie mai mare de comenzi laolaltă. De asemenea, structurile repetitive (for, while) și cele decizionale (if, else) pot fi implementate ușor folosind shell scripting. Operatorii logici sunt și ei des folosiți pentru a înlănțui mai multe comenzi, la fel ca și pipe-urile (“|”) - folosite pentru a folosi output-ul unei comenzi în comanda următoare.

Mai jos este un demo cu comenzile cele mai folosite pentru shell scripting și pentru a automatiza lucrul în linia de comandă.

Comanda grep

Comanda grep extrage liniile care conțin o expresie regulata dată dintr-un fișier.

student@uso:~/Documents$ cat cap_si_pajura | grep frate
Am fost frate pentru frate. x2
Ca nu e si fratele tau
Am fost frate pentru frate. x2
Am fost frate pentru frate. x2

Comenzile head și tail

Comenzile head si tail sunt folosite pentru afișarea primelor/ultimelor linii sau caractere dintr-un input

student@uso:~/Documents$ cat cap_si_pajura | grep frate | head -2
Am fost frate pentru frate. x2
Ca nu e si fratele tau
student@uso:~/Documents$ cat himalaya | grep bani | tail -3
Tot aşa găsesc eu banii şi în vârful munţilor.
Eu fac bani şi-n Himalaya
Unde fac eu bani pachete, duşmanii culeg doar pietre…

Comanda seq

Comanda seq este folosită pentru a genera o secvență de numere. Flagul -s este folosit pentru a stabili caracterul care delimitează numerele. Delimitatorul implicit este ‘\n’.

student@uso:~$ seq 4
1
2
3
4
student@uso:~$ seq -s " " 1 2 5
1 3 5

În comanda de mai sus 1 reprezintă numarul de la care pornim numărătoarea, 2 este incrementul, iar 5 este numărul la care ne oprim. Opțiunea -f este folosită pentru a afișa secvența într-un anumit format.

student@uso:~$ seq -f "Star Wars Episode %01g" 3
Star Wars Episode 1
Star Wars Episode 2
Star Wars Episode 3
student@uso:~$

Comanda cut

Comanda cut este folosită pentru a tăia aceeași secțiune din fiecare linie a unui input și a afișa aceste părți ale liniilor. De exemplu, pentru următorul fișier vrem să afișăm doar numele filmelor, nu și anul în care a avut loc premiera fiecăruia.

student@uso:~$ cat asok.txt
Inception 2010
Parasite 2019
Se7en 1995
Goodfellas 1990
Gladiator 2000
Alien 1979
student@uso:~$ cut -d " " -f 1 asok.txt
Inception
Parasite
Se7en
Goodfellas
Gladiator
Alien
student@uso:~$

Opțiunea -f se folosește pentru a selecta ce coloane din input vrem să fie afișate, iar opțiunea -d definește delimitatorul dintre coloane.

Comanda sed

Comanda sed se poate folosi cu mai multe scopuri, sed fiind un stream editor avansat. Se folosește în principal pentru inserții sau șteregere de caractere într-un input.

student@uso:~$ cat text.txt
Noi ştim că unu ori unu fac unu,
dar un inorog ori o pară
nu ştim cât face.
Ştim că cinci fără patru fac unu,
dar un nor fără o corabie
nu ştim cât face.
student@uso:~$ sed 's/unu/bani/' text.txt
Noi ştim că bani ori unu fac unu,
dar un inorog ori o pară
nu ştim cât face.
Ştim că cinci fără patru fac bani,
dar un nor fără o corabie
nu ştim cât face.
student@uso:~$

În exemplul de mai sus, prima apariție de pe fiecare linie a cuvântului “unu” este înlocuită cu “bani”. Caracterul s care vine imediat după sed indică operația care se face pe input (substitution).

Mai jos sunt schimbate toate aparițiile cuvântului “unu”.

student@uso:~$ sed 's/unu/bani/g' text.txt
Noi ştim că bani ori bani fac bani,
dar un inorog ori o pară
nu ştim cât face.
Ştim că cinci fără patru fac bani,
dar un nor fără o corabie
nu ştim cât face.
student@uso:~$

Comanda se poate folosi și pentru a șterge linii din input.

student@uso:~$ sed '3d' text.txt
Noi ştim că unu ori unu fac unu,
dar un inorog ori o pară
Ştim că cinci fără patru fac unu,
dar un nor fără o corabie
nu ştim cât face.

Comanda de mai sus șterge a treia linie. Mai jos se șterge linia care conține secvența de caractere “cinci”.

student@uso:~$ sed '/cinci/d' text.txt
Noi ştim că unu ori unu fac unu,
dar un inorog ori o pară
nu ştim cât face.
dar un nor fără o corabie
nu ştim cât face.

Folosind regex-uri, putem face pattern matching destul de ușor folosind această comandă. De exemplu, comanda de mai jos șterge linia care conține string-ul “nu” la începutul unui șir.

student@uso:~$ sed '/^nu/d' text.txt
Noi ştim că unu ori unu fac unu,
dar un inorog ori o pară
Ştim că cinci fără patru fac unu,
dar un nor fără o corabie
student@uso:~$

Comanda wc

Comanda wc este folosită pentru a număra liniile, cuvintele sau carcterele dintr-un input.

student@uso:~$ cat yossa
Can you live without answers? All of you, ask that of yourself. Can you live without answers?
Because if you cannot, then most assuredly you will invent your own answers and they will comfort
you. And all those who do not share your view will by their very existence strike fear and hatred
into your heart.
student@uso:~$ wc yossa
  4  56 307 yossa

4 este numărul de linii, 56 este numărul de cuvinte, iar 307 este numărul de caractere.

for, while, if, else

Înainte de a prezenta aceste instrucțiuni, trebuie să înțelegem ce presupune folosirea caracterului $ in niște situații.

$(command) - se înlocuiește cu output-ul comenzii “command”

student@uso:~$ echo Output-ul este $(echo acesta)
Output-ul este acesta
student@uso:~$

$(var) - valoarea ce se găsește în variabila var

student@uso:~$ a=5
student@uso:~$ echo $a
5
student@uso:~$

Instructiunea if

Sintaxa lui if este următoarea:

if [ conditie ]
then
   comenzi
fi

Pe lângă aceasta mai putem avea și if-else sau if-elif-else-fi spre exemplu

if [ conditie ]
then
   comenzi pentru conditie true
else
   comenzi pentru conditie false
fi
if [ conditie1 ]
then
   comenzi pentru conditie1 true
elif [ conditie2 ]
then
   comenzi pentru conditie2 true
else
   comenzi pentru conditie2 false
fi

Mai jos este un exemplu de folosire a unui if într-un script. Sintaxele diferite de mai sus funcționează la fel ca cele pe care le știm de la programare. În schimb, condițiile sunt cele care necesită un plus de atenție.

#!/bin/bash

a=6
b=7
if [[ $a -eq $b ]]
then
		echo "Numerele sunt egale"
elif [[ $a -gt $b ]]; 
then
		echo "a mai mare decat b"
else
		echo "b mai mare decat a"
fi

student@uso:~$ ./script.sh
b mai mare decat a
student@uso:~$

Instrucțiunile for și while pot fi folosite atât în cadrul terminalului în comenzi, cât și în script-uri. Mai jos este un exemplu cu loop-ul for folosit într-o comandă

student@uso:~$ for v in $(seq 1 4); do echo linia $v; done
linia 1
linia 2
linia 3
linia 4

For poate fi folosit si intr-un script.

student@uso:~$ cat script.sh
#!/bin/bash

a=0;
for v in $(seq 1 4)
do
	a=$(($a + $v));
done
echo $a;
student@uso:~$ ./script.sh
10
student@uso:~$

Script-ul de mai sus afișează suma numerelor de la 1 la 4. În același mod poate fi folosit și while:

#!/bin/bash

i=0;
while [ $i -le 3 ]
do
   	 		echo $i
    			i=$(($i+1))
done

Script-ul afișează valorile de la 0 la 3

student@uso:~$ ./script.sh
0
1
2
3
student@uso:~$

Mai jos avem un script care pune la sfârșitul liniilor pare dintr-un text un string:

#!/bin/bash

nr_linii=$(wc -l text.txt | cut -d " " -f 1)
i=0
while [ $i -le $nr_linii ]
do
    			if [[ $(($i%2)) -eq 0 && $i -gt 0 ]]
    			then
   	 			sed -i "$i s/$/ yeah/" text.txt
    			fi
    			i=$(($i+1))
done

Se observă că acest script folosește atât un while, cât și un if, precum și comanda sed.

student@uso:~$ cat text.txt
California, rest in peace
Simultaneous release
California, show your teeth
She's my priestess
I'm your priest
student@uso:~$ ./script.sh
student@uso:~$ cat text.txt
California, rest in peace
Simultaneous release yeah
California, show your teeth
She's my priestess yeah
I'm your priest
student@uso:~$
uso/cursuri/curs-06.txt · Last modified: 2022/11/07 15:27 by sergiu.weisz
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0