Leksion 07 - Scripting


Ambjenti i zhvillimit


Skriptet mund ti krijoni me editorin e tesktit qe preferoni. Me pas duhet ti jepni te dretja ekzekutimi skedarit Tuaj.
Pas kesaj eshte e mundur qe te therrisni skriptin.

Per shembull po krijojme nje skript me emrin hello.world ne dosjen tone /home

[root@localhost student]# cat ./hello.world
#!/bin/bash
echo "hello world"

Do ti lejojme te drejta ekzektutimi per te gjithe mbi skedarin tone:

[root@localhost student]# chmod a+x ./hello.world 
[root@localhost student]# ls -l hello.world 
-rwxr-xr-x. 1 root root 31 Apr  1 01:26 hello.world
[root@localhost student]#



Tani mund ta therrasim skriptin tone te pare:

[root@localhost student]# ./hello.world 
hello world
[root@localhost student]#


Simbolet e vecanta


 Simboli Emertimi Kuptimi Shembull
 # Diezis Perdoret per te sinjalizuar nje koment. Cdo tekst i rreshtit qe ndodhet pas # konsiderohet si koment
 
# This line is a comment.
 " Thonjeza dyshe
 Thonjezat dyshe perdoren per te rrethuar tekstet. Nese ka variabla brenda nje teksti te rrethuar me thonjeza dyshe atehere zevendesohet vlera e atij varialbli
#double quoted string 
echo "this script is running with UID $UID
with root privileges"

 ' Thonjeza teke
 Thonjezat teke perdoren per te rrethuar tekstet. ese ka variabla brenda nje teksti te rrethuar me thonjeza dyshe atehere NUK zevendesohet vlera e atij varialbli #single quoted string
    echo 'this script is running with UID $UID with root privileges'

 ; Pikepresje
 Pikepresja sherben per te ndare komandat nga njera tjetra ( command separator). Na lejon te vendosim dy komanda ne te njejtin rresht.
 
echo hello; echo there
 ;; Dy pikepresje
 Terminator ne instruksionin case. I ngjashem me break ne C.
 case "$variable" in
  abc)  echo "\$variable = abc" ;;
  xyz)  echo "\$variable = xyz" ;;
esac
 , Presja Lidh disa shprehje si ne gjuhen C.Vlera e te gjithe shprehjeve eshte e barabarte me shprehjen me ne te djathte. 
 






Variablat

Variablat nuk eshte e nevojshme qe te deklarohen paraprakisht. Variablat kane tipe dinamike. Ato i marrin tipet mbi bazen e vleres qe kane.
Per te krijuar nje variabel mjafton qe ti japim vlere atij.
Nese duam ti referohemi vleres se tij do te perdorim si prefix shenjen e $. 
Emri i variablit nuk paraprihet nga shenja $ ne momentin e krijimit te tij ose ne instruksione vleredhenie, ku i jepet vlere atij variabli.





Per shembull:

[root@localhost student]# cat hello.world 
#!/bin/bash
mesazh="Pershendetje nga skripti"
echo $mesazh

nese do ta therrasim skriptin:

[root@localhost student]# ./hello.world 
Pershendetje nga skripti
[root@localhost student]#


Zevendesimi i variablave ( variable substitution )


Emri i variablit eshte nje shenjues ne bytine e pare te zones se memorjes ku ruhet vlera e variablit.
Kapja e vleres se variablit quhet zevendesim i variablit ose "variable substitution"

Emrat e variablave paraprihen nga shenja e dollarit $ , sa here qe ata referohen, me perjashtim te rastit te vleredhenies dhe te "export" me $((myvar+1 )) ne nje shprehje aritmetike.


[student@localhost ~]$ myvar=1
[student@localhost ~]$ echo $myvar
1
[student@localhost ~]$ 

Vleredhenia
Nje variabel mund te marre vlere :
  • nepermjet nje isntruksioni vleredhenie myvar=1
  • nepermjet funksionit read
  • nepermjet nje cikli psh for myvar in 1 2 3
Ne rastin  e nje instruktioni vleredhenie nuk lejohet hapesira:
  • midis emrit te variablit dhe operatorit te vleredhenies =
  • operatorit te vleredhenies =  dhe vleres se variablit

Kodi :

[student@localhost ~]$ myvar =1
bash: myvar: command not found

gjeneron gabim, po keshtu edhe kodi

[student@localhost ~]$ myvar= 1
bash: 1: command not found

gjeneron gabim, ndersa kodi eshte i sakte pasi nuk ka hapesire as perpara dhe as pas shenjes se barazimit.

[student@localhost ~]$ myvar=1
[student@localhost ~]$ 

Operatori let
Variablat mund ti jepet vlere gjithashtu duke perdorur operatorin let. Shembulli me poshte ilustron sintaksen:

[student@localhost ~]$ let myvar=20

Thonjezat mbrapsht ` `
Thonjezat mbrapsht mund te perdoren per te kthyer vleren e nje komande,

per shembull

[student@localhost ~]$ echo `echo "hello world" `
hello world
[student@localhost ~]$

Zevendesimi i komandave me $( komande)

Nje menyre me e mire per efekt te lexueshmerise se kodit do te ishte $( komande )

[student@localhost ~]$ echo $(echo "hello world")
hello world
[student@localhost ~]$


ose 

[student@localhost ~]$ echo $(ls /home)
krista krista2 level1 lost+found student
[student@localhost ~]$


Tipet e variblave ( tekst apo numer)

Variablat i marrin tipet ne menyre dinamike ne varesi te vleres se tyre. 
Ne varesi te tipit te variablit trajtohen edhe veprimet aritmetike. Kujtojme qe + eshte veprimi aritmetik i mbledhjes por ne te njejten kohe eshte dhe operatori i konkatenimit te stringjeve. 
Vini re shembullin me poshte

[student@localhost ~]$ echo $a
student
[student@localhost ~]$ a+=1
[student@localhost ~]$ echo $a
student1
[student@localhost ~]$


Nese variablit a qe ka vlere tekst i shtojme 1 veme re qe rezultati eshte nje "1" i shtuar ne fund te fjales.

Ndersa nese duam qe te zevendesojme variablat ne nje shprehje aritmetike atehere do te perdorim dy here kllapat e rrumbullaketa:


[student@localhost ~]$ echo a=$a,b=$b
a=student,b=1

[student@localhost ~]$ echo $((a+b))
1
[student@localhost ~]$ a=3
[student@localhost ~]$ echo $((a+b))
4
[student@localhost ~]$



unset
Per te fshire nje variabel perdorim funksionin unset, si me poshte:

[student@localhost ~]$ echo $myvar

[student@localhost ~]$ myvar=10
[student@localhost ~]$ echo $myvar
10
[student@localhost ~]$ unset myvar
[student@localhost ~]$ echo $myvar

[student@localhost ~]$


weak quoting vs strong quoting

Vendosja e references se nje variabli ( me $) midis thonjezave ka efekte te ndryshme midis thonjezave dyshe (qe quhet "weak quoting") dhe tonjezave teke ( qe quhet " strong quoting".
Kodi me poshte ilustron dallimin midis weak dhe strong quoting:

[student@localhost ~]$ echo "$myvar"
1
[student@localhost ~]$ echo '$myvar'
$myvar
[student@localhost ~]$






Strukturat e kontrollit



if then else


Sintaksa e pergjithshme e instruksionit if then else eshte:

Shenim pikepresja eshte vendosur pasi shprehja e ndare me hapesire nga kllapat eshte vendosur ne nje rresht me then

if [ shprehje ] ; then  

    instruktione

else

    instruksione

fi


ose pa vendosur pikepresje por ne kete rast duhet te kalojme then ne rreshtin pasardhes

if [ shprehje ]  
then

    instruktione

else

    instruksione

fi




Ushtrim
Ekzekutoni tre skriptet e meposhtme dhe sqaroni ne cdo rast ne se ka gabim cili eshte gabimi:


   Shenime
 Skripti 1
 #!/bin/bash
 if [ $UID = 0 ] then
    # double quoted string    
    echo "this script is running with UID $UID
         with root privileges" 

    #single quoted string
    echo 'this script is running with UID $UID
                 with root privileges'

    echo $USER
else
    echo  "this script is not running
         with root provileges"
    
    echo $USER
fi

 
   
 Skripti 2
 #!/bin/bash

if [ $UID = 0 ]; then
    # double quoted string    
    echo "this script is running with UID $UID
         with root privileges" 

    #single quoted string
    echo 'this script is running with UID $UID
                 with root privileges'

    echo $USER
else
    echo  "this script is not running
         with root provileges"
    
    echo $USER
fi

 
   
 Skripti 3
 #!/bin/bash

if [ $UID = 0 ]
then
    # double quoted string    
    echo "this script is running with UID $UID
         with root privileges" 

    #single quoted string
    echo 'this script is running with UID $UID
                 with root privileges'

    echo $USER
else
    echo  "this script is not running
         with root provileges"
    
    echo $USER
fi

 



Cikli for

Cikli for ka nje implementim te ndryshem nga gjuha C. Cikli for sherben per te iteruar ne nje liste me vlera per shembull:

#!/bin/bash
mesazh="Pershendetje nga skripti"
echo $mesazh
for i in $(ls); do
echo $i
done



Skripti do te afishonte permbajtjen e dosjes korrente

[root@localhost student]# ./hello.world 
Pershendetje nga skripti
Desktop
Documents
Downloads
hello.bsh
hello.world
Music
Pictures
Public
slaes
Templates
Videos
[root@localhost student]#

Lista e vlerave ne te cilen merr vlere variabli mund te jete fikse , mund te jete interval ose rezultati i nje komande si ne rastin e pare  ( lista perbehej nga vlerat qe kthene komanda ls)

Shembujt me poshte ilustrojne perdorimin e ciklit for per te iteruar ne nje sekuence numrash


for i in {1..5}; do
echo $i
done


do te afishonte:

[root@localhost student]# ./hello.world 
1
2
3
4
5
[root@localhost student]#

ndersa 

#!/bin/bash

for i in {5..1}; do
echo $i
done

do te afishonte


[root@localhost student]# ./hello.world 
5
4
3
2
1
[root@localhost student]#

Ndersa 
#!/bin/bash

for i in  2  4 6;  do
echo $i
done


do te afishonte numrat nga 2 deri tek 6

[root@localhost student]# ./hello.world 
2
4
6
[root@localhost student]# 



Cikli while

Cikli while merr si argument nje kusht llogjik dhe iteron per sa kohe kushti eshte i vertete

Shembulli me poshte ilustron kete perdorim:


         #!/bin/bash 
         COUNTER=0
         while [ $COUNTER -lt 10 ]; do
             echo The counter is $COUNTER
            let  COUNTER=$COUNTER+1 
         done



Cikli until

Cikli until eshte i kunderti i ciklit while. Ehe until merr si argument nje kusht llogjik por  iteron per sa kohe kushti nuk eshte i vertete.

#!/bin/bash
COUNTER=6
until [ $COUNTER -lt 1 ]; do
echo The counter is $COUNTER
let COUNTER=$COUNTER-1
done

Shembulli me lart do te afishonte numrat nga 6 tek 1

[root@localhost student]# ./hello.world 
The counter is 6
The counter is 5
The counter is 4
The counter is 3
The counter is 2
The counter is 1
[root@localhost student]#


Operatoret e krahasimit

Per te shmagur gabimet qe mund te shkaktohen nga perdorim i simboleve te krahasimit <,> qe jane gjithashtu edhe operatoret e ridrejtimit ekzistojne operatoret te tjere krahasimi qe mund te perdoren per te formuar shprehjet llogjike. 

integer comparison

-eq

is equal to

if [ "$a" -eq "$b" ]


-ne

is not equal to

if [ "$a" -ne "$b" ]


-gt

is greater than

if [ "$a" -gt "$b" ]


-ge

is greater than or equal to

if [ "$a" -ge "$b" ]


-lt

is less than

if [ "$a" -lt "$b" ]


-le

is less than or equal to

if [ "$a" -le "$b" ]


<

is less than (within double parentheses)

(("$a" < "$b"))


<=

is less than or equal to (within double parentheses)

(("$a" <= "$b"))


>

is greater than (within double parentheses)

(("$a" > "$b"))


>=

is greater than or equal to (within double parentheses)

(("$a" >= "$b"))


Operatoret mbi stringjet


=

is equal to

if [ "$a" = "$b" ]

Shenim
kujdes hapesirat



!=

is not equal to

if [ "$a" != "$b"



Shenim
Ky operator se bashku me == qe eshte sinonim i = mund te realizojne patern matching ( kerkime me karaktere te vecanta psh z*) nese vendosen midis dy kllapave katrore 


-Z 

stringu eshte null, me gjatesi 0 karaktere

if [ -z "$1" ]; then 
echo usage: $0 directory
exit



Funksionet


Krijimi i funksioneve dhe therritja e tyre 
(shembulli)

#!/bin/bash

function sayhello()
{
msg=$1
echo  $msg
}


COUNTER=6
until [ $COUNTER -lt 1 ]; do
        sayhello " The counter is $COUNTER"
        let COUNTER=$COUNTER-1
done




Nderfaqa me perdoruesin


Komanda select

Qendron brenda komandes derisa te therritet exit

 #!/bin/bash
           menu="Hello Quit"
           select opt in $menu; do
               if [ "$opt" = "Quit" ]; then
                echo done
                exit
               elif [ "$opt" = "Hello" ]; then
                echo Hello World
               else
                clear
                echo bad option
                echo "1) Hello"
                echo "2) Quit"
               fi
           done


Kapja e argumentave ne therritje te skriptit


 #!/bin/bash        
          if [ -z "$1" ]; then 
              echo usage: $0 directory
              exit
        
      else
        arg=$1
        echo "you entered" $arg
        fi




Leximi i input te perdoruesit me funksionin read



 #!/bin/bash        

echo " Shkruani emrin tuaj"
read emri
echo  " shkruani mbiemrin tuaj"
read mbiemri
echo "Mire se erdhet $emri $mbiemri"

Veprimet aritmetike

Nje shprehje aritmetike fillon me shenjen e dollarit dhe vendos ne kllapa te rrumbullaketa te dyfishta:

 #!/bin/bash        

echo " Shkruani numrin e pare"
read nr1
echo  " shkruani numrin e dyte "
read nr2
sh=$(($nr1+$nr2))
echo "shuma e $nr1 me $nr2 eshte= $sh"



Date & Time

Variabli date kthen kohen e momentit Duke perdorur nje maske mund te formatohet data sipas formatit te deshiruar.
Shpesh per  te gjeneruar emra unke skedarish si ne rastin e backup i bashkengjitete koha e backup skedarit si nje prapashtese.

Sintaktsa per te formatiar daten eshte

date +format

shikoni shembullin me poshte:

[root@localhost student]# date +%m-%d-%Y%k:%M:%S
04-01-2014 4:29:48

Tabela me poshte liston flaget e mundshme te formatimit te dates:

%FORMAT StringDescription
%%a literal %
%alocale's abbreviated weekday name (e.g., Sun)
%Alocale's full weekday name (e.g., Sunday)
%blocale's abbreviated month name (e.g., Jan)
%Blocale's full month name (e.g., January)
%clocale's date and time (e.g., Thu Mar 3 23:05:25 2005)
%Ccentury; like %Y, except omit last two digits (e.g., 21)
%dday of month (e.g, 01)
%Ddate; same as %m/%d/%y
%eday of month, space padded; same as %_d
%Ffull date; same as %Y-%m-%d
%glast two digits of year of ISO week number (see %G)
%Gyear of ISO week number (see %V); normally useful only with %V
%hsame as %b
%Hhour (00..23)
%Ihour (01..12)
%jday of year (001..366)
%khour ( 0..23)
%lhour ( 1..12)
%mmonth (01..12)
%Mminute (00..59)
%na newline
%Nnanoseconds (000000000..999999999)
%plocale's equivalent of either AM or PM; blank if not known
%Plike %p, but lower case
%rlocale's 12-hour clock time (e.g., 11:11:04 PM)
%R24-hour hour and minute; same as %H:%M
%sseconds since 1970-01-01 00:00:00 UTC
%Ssecond (00..60)
%ta tab
%Ttime; same as %H:%M:%S
%uday of week (1..7); 1 is Monday
%Uweek number of year, with Sunday as first day of week (00..53)
%VISO week number, with Monday as first day of week (01..53)
%wday of week (0..6); 0 is Sunday
%Wweek number of year, with Monday as first day of week (00..53)
%xlocale's date representation (e.g., 12/31/99)
%Xlocale's time representation (e.g., 23:13:48)
%ylast two digits of year (00..99)
%Yyear
%z+hhmm numeric timezone (e.g., -0400)
%:z+hh:mm numeric timezone (e.g., -04:00)
%::z+hh:mm:ss numeric time zone (e.g., -04:00:00)
%:::znumeric time zone with : to necessary precision (e.g., -04, +05:30)
%Zalphabetic time zone abbreviation (e.g., EDT)


Shkrimi ne skedare me emra te bazuar ne kohen e ekzekutimit


Shembull

#!/bin/bash
file="sample.txt."$(date +%d-%m-%Y_%k:%M:%S)
#touch $file
#echo $file
echo "hello" > "$file"


Llogatitja e kohezgjatjes se nje veprimi

#!/bin/bash
start=$(date +%s)
echo "Start on $start"

for i in {1..1000000}
{
d=100
}

end=$(date +%s)

echo "Ended on $end"

diff=$(($end-$start))

echo "duration: $diff"


Shtimi ose heqja e njesive  nga nje date

Shembuj

[root@localhost student]# date -d 'now'
Tue Apr  1 05:08:47 PDT 2014

[root@localhost student]# date -d 'now + 3 weeks'
Tue Apr 22 05:08:56 PDT 2014

[root@localhost student]# date -d 'now + 3 days'
Fri Apr  4 05:09:08 PDT 2014

[root@localhost student]# date -d 'now + 3 months'
Tue Jul  1 05:09:13 PDT 2014

[root@localhost student]# date -d 'now + 3 years'
Sat Apr  1 05:09:21 PDT 2017

[root@localhost student]# date -d 'now - 3 years'
Fri Apr  1 05:09:38 PDT 2011


Ushtrime


1-  Leximi i skedarit emri i te cilit eshte argument i skriptit

Ndertoni nje skript qe merr si argument nje skedar dhe afishon permbajtjen e tij. Nese skripti nuk e merr skedarin si argumetn duhet te njoftoje perdoruesin per menyren si duhet ta therrase skriptin

Zgjidhje

skript1.sh
if [ -z "$1" ]
then
echo usage: $0 file to read
exit
fi


while read line
do
echo $line
done < "$1"



2- Komunikimi me perdoruesin ne skript

Ndertoni nje skript qe i kerkon perdoruesit te fuse dy numra. Skripti do te gjeje dhe afishoje shumen e ketyre dy numrave

calculator.sh
#1/bin/bash
echo "Futni numrin e pare"
read nr1
echo "Futni numrin e dyte"
read nr2
shuma = $( "$nr1" + "$nr2" )
echo "shuma eshte= $shuma"


3- Funksionet me kohen

Modifikoni skriptin calculator ne menyre te tille qe ne perfundim te shfaqe sa sekonda qendroi skripti ne ekzekutim:

calculator2.sh

#1/bin/bash
clear
start=$(date +%s)
s2=$(date +%m-%d-%Y%k:%M:%S)
echo "Skripti filloi ekzekutimin ne  $s2"
echo " e konvertuar ne sekonda " $start
echo "****************************************"

echo "Futni numrin e pare"
read nr1
echo "Futni numrin e dyte"
read nr2
shuma=$((nr1 + nr2))
echo "shuma eshte= $shuma"

end=$(date +%s)
e2=$(date +%m-%d-%Y%k:%M:%S)
echo "****************************************"
echo "Skripti e perfundo ekzekutimin ne $e2"
koha=$(($end-$start))
echo "Skripti u ekzekutua per $koha sekonda"



4- Leximi i skedarit

Ndertoni nje skript qe merr si argument nje skedar dhe afishon permbajtjen e tij. Nese skripti nuk e merr skedarin si argument atehere duet te pyese perdoruesin per emrin e skedarit. Pasi te lexoje emrin e ksedarit nga perdoruesi duhet te afishoje ate rresht per rresht. Skripti duhet te ndertoje nje funksion i cili lexon skedarin dhe e afishon rresht per rresht dhe ta therrase ate funksion. Funksioni do ta marre emrin e skedarit si argument.

zgjidhje

clear

if [ -z "$1" ]
then
echo Give the name of the file to read
read fname
else
fname="$1"
fi
readfile $fname


function readfile()
{
while read line
do
echo $line
done < "$1"
}



Nese do ta therrisnim skriptin me lart do te merrnim nje mesazh gabimi si me poshte:

Give the name of the file to read
test
./filerw3: line 14: readfile: command not found
[student@localhost ~]$

Cila eshte arsyeja?


Pse versioni i meposhtem i skriptit nuk jep gabim?

function readfile()
{
while read line
do
echo $line
done < "$1"
}

clear

if [ -z "$1" ]
then
echo Give the name of the file to read
read fname
else
fname="$1"
fi
readfile $fname


5- Numerimi i rreshtave te skedarit

Modifikoni skriptin e pikes 4 ne menyre te tille qe te gjeje dhe te afishoje numrin e rreshtave qe ka funksioni

zgjidhje

function readfile()
{
while read line
do
echo $line
done < "$1"
}

function count()
{
counter=0
while read line
do
let counter=$counter+1
echo $counter $line
done < "$1"
return $counter
}


clear

if [ -z "$1" ]
then
echo Give the name of the file to read
read fname
else
fname="$1"
fi
readfile $fname
count $fname
ret=$?
echo $ret









5- Shuma e numrave qe gjenen ne rreshtat e nje skedarit

Modifikoni skriptin e pikes 4 ne menyre te tille qe duke supozuar qe skedari qe merr si argument permban nje liste me numra ( nje numer ne nje rresht) gjen dhe afishon shumen e atyre numrave

function readfile()
{
while read line
do
echo $line
done < "$1"
}

function count()
{
counter=0
while read line
do
let counter=$counter+1
echo $counter $line
done < "$1"
return $counter
}

function sum()
{
s=0
while read line
do
s=$(($s+$line))
echo $s $line
done < "$1"
return $s
}


clear

if [ -z "$1" ]
then
echo Give the name of the file to read
read fname
else
fname="$1"
fi
readfile $fname
count $fname
ret=$?
# vlera qe kthen funksioni menjehere me lart
echo File $fname has $ret rows
sum $fname
ret=$?
echo sum of numbers in  $fname is $ret