La shell di Linux
Download
Report
Transcript La shell di Linux
La shell di Linux
Linux ha una varietà di shell differenti:
Bourne shell (sh), C shell (csh), Korn shell (ksh), TC
shell (tcsh), Bourne Again shell (bash).
Sicuramente la shell più popolare è “bash”. Bash è
la shell che è stata introdotta nel sistema operativo
GNU. Bash è una shell sh-compatibile che
incorpora utili caratteristiche della Korn shell (ksh)
e della C shell (csh).
Bash è conforme allo standard IEEE POSIX
P1003.2/ISO 9945.2 Shell and Tools.
Garantisce miglioramenti funzionali rispetto a sh
sia per programmare che per l’uso interattivo.
1.1
Programming o Scripting ?
Bash non è soltanto un’eccellente interprete di comandi, ma
un vero e proprio supporto per un linguaggio di script. Il
linguaggio di script della shell permette di utilizzare le
potenzialità della shell e di automatizzare un mucchio di
compiti che richiederebbero altrimenti una grande quantità
di comandi.
Differenza tra linguaggi di programmazione e linguaggi di
script:
I linguaggi di programmazione sono in genere notevolmente più
potenti e veloci dei linguaggi di script. I linguaggi di programmazione
generalmente partono dal codice sorgente e vengono compilati in un
eseguibile. Tale eseguibile non è facilmente portabile su differenti
sistemi operativi.
Un linguaggio di script parte a sua volta dal codice sorgente, ma non
viene compilato in un eseguibile. Piuttosto, un interprete legge le
istruzioni nel file sorgente ed esegue ciascuna istruzione. I
programmi interpretati sono in genere più lenti dei programmi
compilati. Il vantaggio principale è che si può facilmente portare il
file sorgente su ogni sistema operativo. Bash è un linguaggio di
script. Altri esempio di linguaggi di script sono Perl, Lisp, e Tcl.
1.2
Il primo programma bash
Occorre sapere come usare un editor di testo. Ci
sono due editor di testo principali in Linux:
vi (o vim), emacs (o xemacs).
Dunque lanciamo un editor di testo; ad esempio:
$ vi &
e digitiamo ciò che segue:
#!/bin/bash
echo “Hello World”
La prima linea dice a Linux di utilizzare l’interprete
bash per eseguire questo script. Lo chiameremo
hello.sh. Ora rendiamo lo script eseguibile:
$ chmod 700 hello.sh
$ ls –l
-rwx------ hello.sh
1.3
Il primo programma bash
Per eseguire il programma:
$ hello.sh
-bash: hello.sh: command not found
La directory home (in cui il comando hello.sh si trova)
non si trova fra quelle elencate nella variabile d’ambiente PATH
echo $PATH
:bin:/usr/bin:…
Occorre specificare il path di hello.sh
$/home/srinaldi/Scripts/hello.sh
$./hello.sh
1.4
Il secondo programma bash
Scriviamo un programma che copia tutti i files in una
directory, e poi cancella la directory con tutto il suo
contenuto. Ciò può essere fatto col seguente comando:
$ mkdir trash
$ cp * trash
$ rm -rf trash
Invece di essere costretti a digitare tutto ciò in modo
interattivo nella shell, scriviamo uno script di shell:
$ cat > trash
#!/bin/bash
# this script deletes some files
mkdir trash
cp * trash
rm -rf trash
echo “Deleted all files!”
1.5
Variabili
Si possono usare le variabili come in ogni linguaggio di
programmazione. I loro valori sono sempre memorizzati
come stringhe, ma ci sono delle strutture nel linguaggio di
shell che convertono le variabili in numeri per fare i calcoli.
Non c’è bisogno di dichiarare una variabile, il solo fatto di
assegnarle un valore la crea automaticamente.
Esempio
#!/bin/bash
STR=“Hello World!”
echo $STR
La linea 2 crea una variabile detta STR e assegna la stringa
"Hello World!" ad essa. Quindi il valore di questa variabile
viene recuperato mettendo il '$' all’inizio.
1.6
Attenzione!
Il linguaggio della shell non tipizza (assegna un tipo a) le
variabili. Ciò significa che una variabile può contenere dati
numerici o alfabetici.
count=0
count=Sunday
Cambiare il tipo di una variabile può generare confusione,
sia per chi scrive lo script che per qualcuno che cerca di
modificarlo, pertanto è raccomandato l’uso di un solo tipo di
dati per ogni singola variabile all’interno di uno script.
\ è il carattere di escape di bash, e conserva il valore
letterale del carattere che segue.
$ ls \*
ls: *: No such file or directory
1.7
Virgolette singole e doppie
Quando si assegnano dati contenenti spazi o caratteri speciali, i dati
devono essere racchiusi tra virgolette (singole o doppie).
Quando si usano virgolette doppie (partial quoting) per stampare a
video una stringa di caratteri, ogni variabile verrà sostituita dal valore
che essa assume in quel momento.
$ var=“test string”
$ newvar=“Value of var is $var”
$ echo $newvar
Value of var is test string
L’uso di virgolette singole (full quoting) per visualizzare una stringa di
caratteri non permette la risoluzione delle variabili.
$ var=’test string’
$ newvar=’Value of var is $var’
$ echo $newvar
Value of var is $var
1.8
Esempi vari
$ pippo= pluto
$ pippo =pluto
$ ls [Pp]*
$ ls “[Pp]*”
$ ls ‘[Pp]*’
$
$
$
$
errore
Not resolved
var=“’(]\\{}\$\””
echo $var
echo “$var”
echo ‘$var’
$ echo \z
$ echo \\z
$ echo ‘\\z’
# z
# \z
# \\z
1.9
Esempi vari
$ pippo=cat
$ echo “comando = \” $pippo \” “
comando =“ cat ”
$ echo ‘comando = \” $pippo \” ‘
comando =\” $pippo \”
$ echo ‘comando = ” $pippo ” ‘
comando =” $pippo “
1.10
Il comando export
Il comando export inserisce una variabile nell’ambiente, così che essa sarà
accessibile ai processi figli. Per esempio:
$ x=hello
$ bash # Run a child shell.
$ echo $x
# Nothing in x.
$ exit
# Return to parent.
$ export x
$ bash
$ echo $x
hello
# It's there.
Se il processo figlio modifica x, non verrà modificato il valore originale nel
processo padre. Si verifichi tale fatto cambiando x nel modo seguente:
$ x=ciao
$ exit
$ echo $x
hello
1.11
Variabili di ambiente
Ci sono due tipi di variabili:
Variabili locali
Variabili di ambiente
Le variabili di ambiente sono definite a livello di sistema e
possono di norma essere reperite usando il comando env.
Le variabili di ambiente contengono valori speciali. Ad
esempio,
$ echo $SHELL
/bin/bash
$ echo $PATH
/usr/X11R6/bin:/usr/local/bin:/bin:/usr/bin
Le variabili di ambiente sono definite in /etc/profile,
/etc/profile.d/ e ~/.bash_profile. Questi files sono files di
inizializzazione e vengono letti quando la shell bash viene
invocata. Al momento del logout da parte dell’utente, bash
legge ~/.bash_logout.
1.12
Variabili di ambiente
Il pathname della home dell’utente
(l’argomento di default di cd).
PATH: Il “search path” per i comandi. É un elenco
delle directories (separate da :) nelle quali la shell
cerca il comando da eseguire.
Solitamente, si lancia uno script nel modo
seguente:
HOME:
$ ./trash.sh
Ponendo
PATH=$PATH:. la nostra working
directory viene inclusa nel “search path” per i
comandi, e possiamo digitare semplicemente:
$ trash.sh
1.13
Variabili di ambiente
LOGNAME: contiene il nome dell’utente.
HOSTNAME: contiene il nome della macchina.
MACHTYPE: hardware del sistema.
PS1: sequenza di caratteri visualizzata davanti al prompt.
\t ora
\d data
\w current directory
\W ultima parte della current directory
\u nome dell’utente
\$ carattere del prompt
Esempio
[lferrari@homelinux lferrari]$ PS1=‘ciao \u *’
ciao lferrari* _
UID: contiene l’id number dell’utente (non può essere cambiato).
1.14
Il comando exit
Il comando exit può essere usato per terminare
uno script. Esso restituisce un valore, che è
disponibile per il processo padre dello script.
Quando uno script termina col comando exit senza
ulteriori parametri, lo stato di uscita è lo stato di uscita
dell’ultimo comando eseguito nello script.
#!/bin/bash
#!/bin/bash
COMMAND_1
COMMAND_1
. . .
. . .
# exit with status of last command.
COMMAND_LAST
# exit with status of last command.
COMMAND_LAST
exit
exit $?
1.15
Il comando exit
Il comando exit può essere usato per terminare
uno script. Esso restituisce un valore, che è
disponibile per il processo padre dello script.
Quando uno script termina con
exit nnn
dove nnn=0-255, lo stato di uscita è nnn.
1.16
Il Comando read
Il comando read consente di leggere l’input da
tastiera e memorizzarlo in una variabile.
Esempio (read.sh)
1.17
Il Comando read
Opzioni
read –s
(non stampa a video l’input)
read –nN (accetta soltanto N caratteri di input)
read –p “message” (visualizza il messaggio “message”)
read –tT (accetta l’input per T secondi)
Esempio
$ read –s –n1 -p “Yes (Y) or not (N)?” answer
Yes (Y) or not (N) ? (digitare Y: non si vedrà)
$ echo $answer
Y
1.18
Sostituzione dei comandi
La “virgoletta retrograda”, o accento grave, “`” è diversa
dalla virgoletta “´”. Essa viene usata per la sostituzione dei
comandi: `command`
$ LIST=`ls`
$ echo $LIST
hello.sh read.sh
PS1=“`pwd`>”
/home/rinaldi/didattica/>
Possiamo eseguire la sostituzione dei comandi anche
usando $(command)
$ LIST=$(ls)
$ echo $LIST
hello.sh read.sh
rm $( find / -name “*.tmp” )
ls $( pwd )
ls $( echo /bin )
1.19
Esempio
$ a=`echo Hello`
$ echo $a
$ echo ‘$a’
$
$
$
$
b=`ls /home`
echo $b
echo $a $b
echo “$a $b”
1.20
Operatori aritmetici
+
*
/
**
%
somma
sottrazione
moltiplicazione
divisione
esponenziazione
modulo
Esempio
$
$
$
$
a=(5+2)*3
echo $a
b=2**3
echo $a+$b
1.21
Valutazioni aritmetiche
Il costrutto let può essere usato per creare funzioni
matematiche
$ let X=10+2*7
$ echo $X
24
$ let Y=X+2*4
$ echo $Y
32
Non è necessario usare $X
per riferirsi al valore di X
Un’espressione aritmetica può essere valutata usando
$[expression] o $((expression))
$ echo $((123+20))
143
$ VALORE=$[123+20]
$ echo $[10*$VALORE]
1430
$ echo $[2**3]
$ echo $[8%3]
1.22
Costrutti condizionali
Le strutture condizionali ci permettono di decidere
se eseguire un’azione oppure no, a seconda del
valore di un’espressione da valutare. Il costrutto
condizionale fondamentale è:
if [ expression ];
then
statements
elif [ expression ];
then
statements
else
statements
fi
Le parti elif (else if) e else sono opzionali.
1.23
Espressioni
Un’espressione può essere: un confronto fra stringhe, un
confronto fra numeri, un operatore su file, un operatore
logico ed è rappresentata da [ expression ]:
Confronto fra stringhe:
=
!=
-n
-z
per valutare se due stringhe sono uguali
per valutare se due stringhe sono diverse
per valutare se la lunghezza di una stringa è maggiore di
zero
per valutare se la lunghezza di una stringa è uguale a zero
Esempi:
[ s1 = s2 ]
(vero se s1 è uguale a s2, altrimenti falso)
[ s1 != s2 ] (vero se s1 è diverso da s2, altrimenti falso)
[ s1 ]
(vero se s1 è non vuota, altrimenti falso)
[ -n s1 ]
(vero se s1 ha lunghezza maggiore di 0, altrimenti
falso)
[ -z s2 ]
(vero se s2 ha lunghezza 0, altrimenti falso)
1.24
Espressioni
Confronto fra numeri:
-eq
-ge
-le
-ne
-gt
-lt
valuta se due numeri sono uguali
valuta se un numero è maggiore o uguale a un altro
valuta se un numero è minore o uguale a un altro
valuta se due numeri sono diversi
valuta se un numero è maggiore di un altro
valuta se un numero è minore di un altro
Esempi:
[ n1 -eq n2 ] (vero se n1 è uguale a n2, altrimenti falso)
[ n1 -ge n2 ] (vero se n1 è maggiore o uguale a n2, altrimenti
falso)
[ n1 -le n2 ] (vero se n1 è minore o uguale a n2, altrimenti
falso)
[ n1 -ne n2 ] (vero se n1 è diverso da n2, altrimenti falso)
[ n1 -gt n2 ] (vero se n1 è maggiore di n2, altrimenti falso)
[ n1 -lt n2 ] (vero se n1 è minore di n2, altrimenti falso)
1.25
Espressioni
Operatori su files:
-d
controlla se il cammino dato rappresenta una directory
-f
controlla se il cammino dato rappresenta un file ordinario
-e
controlla se il nome del file esiste
-s
controlla se un file ha lunghezza maggiore di 0
-r
controlla se si possiede il permesso di lettura per un file o una directory
-w
controlla se si possiede il permesso di scrittura per un file o una directory
-x
controlla se si possiede il permesso di esecuzione per un file o una
directory
Esempi:
[ -d fname ]
(vero se fname è una directory, altrimenti falso)
[ -f fname ]
(vero se fname è un file ordinario, altrimenti falso)
[ -e fname ]
(vero se fname esiste, altrimenti falso)
[ -s fname ]
(vero se la lunghezza di fname è maggiore di 0, altrimenti
falso)
[ -r fname ]
(vero se fname ha il permesso di lettura, altrimenti falso)
[ -w fname ]
(vero se fname ha il permesso di scrittura, altrimenti falso)
[ -x fname ]
(vero se fname ha il permesso di esecuzione, altrimenti falso)
1.26
Esempio
#!/bin/bash
if [ -f /etc/fstab ];
then
cp /etc/fstab .
echo “Done.”
else
echo “This file does not exist.”
exit 1
fi
Esercizio. Scrivere uno script di shell che prenda in input un
nome di file <pippo>:
Lo script controlla se esiste una cartella Backup, altrimenti la crea.
Se il file cercato esiste, copia il file con lo stesso nome + .bak nella
cartella Backup.
Se il file non esiste, allora visualizza il messaggio “The file <pippo>
does not exist!!!”
1.27
Espressioni
Operatori logici:
!
negare (NOT) un’espressione logica
-a congiunzione (AND) tra due espressioni
logiche
-o disgiunzione (OR) tra due espressioni
logiche
1.28
Espressioni
Operatori logici:
&& congiunzione (AND) tra due espressioni
logiche
|| disgiunzione (OR) tra due espressioni
logiche
1.29
Parametri di shell
Un parametro posizionale corrisponde ad un argomento
fornito alla shell al momento dell’esecuzione di un
programma. Il primo argomento specificato corrisponde alla
variabile 1, il secondo argomento alla variabile 2 e così via.
Il parametro posizionale “N” può essere referenziato come
“${N}”, o come “$N” quando “N” consiste in una singola
cifra.
Parametri speciali
$# è il numero dei parametri passati
$0 rende il nome dello script di shell in esecuzione nonchè la sua
posizione nel file system
$* rende una singola parola contenente tutti i parametri passati allo
script
$@ rende un array di parole contenente tutti i parametri passati allo
script
1.30
Il costrutto case
Viene usato per eseguire azioni basate su valori specifici.
Usato spesso al posto di un costrutto if se c’è un numero
elevato di condizioni.
Il valore usato può essere un’espressione.
Ciascun insieme di azioni deve concludersi con una coppia di punto
e virgola.
Il simbolo *) viene usato per accettare
corrispondente con la lista dei valori.
case $var in
val1)
statements;;
val2)
statements;;
*)
statements;;
esac
1.31
ogni
valore
non
Costrutti di iterazione
Il ciclo for viene usato quando si vuole ripetere un blocco di
comandi in corrispondenza di valori tratti da un elenco.
for var in list
do
istruzioni
done
Le istruzioni vengono eseguite assegnando a var ciascun
valore in list.
#!/bin/bash
let sum=0
for num in 1 2 3 4 5
do
let sum=$sum+$num
done
echo $sum
1.32
Costrutti di iterazione: <list>
#!/bin/bash
for x in paper pencil pen; do
echo “The value of variable x is: $x”
sleep 1
done
# The value of variable x is paper
# The value of variable x is pencil
# The value of variable x is pen
#!/bin/bash
for x in “paper A4” “pencil STADTLER” “pen BIC”; do
echo “The value of variable x is: $x”
sleep 1
done
# The value of variable x is paper A4
# The value of variable x is pencil STADTLER
# The value of variable x is pen BIC
1.33
Costrutti di iterazione: <list>
#!/bin/bash
lista=“antonio
michele
paolo
luca”
for x in $lista
do
echo “The value of variable x is: $x”
sleep 1
done
#
#
#
#
The
The
The
The
value
value
value
value
of
of
of
of
variable
variable
variable
variable
x
x
x
x
is
is
is
is
1.34
antonio
michele
paolo
luca
Costrutti di iterazione: <list>
#!/bin/bash
for x in *
do
ls -l “$x”
sleep 1
done
# Lists all files in current directory
#!/bin/bash
for x in /bin
do
ls -l “$x”
done
# Lists all files in /bin
1.35
Costrutti di iterazione: <list>
#!/bin/bash
read –p “Insert the name of a directory” directory
echo "symbolic links in directory \“ $directory \“ "
for file in $( find $directory -type l ) # -type l = symbolic links
do
echo "$file"
done | sort
# Otherwise file list is unsorted
1.36
Costrutti di iterazione: <list>
Se la parte list viene omessa, a var viene assegnato
ciascun parametro passato allo script ( $1, $2, $3,…).
1.37
Costrutti di iterazione: <list>
Se la parte list viene omessa, a var viene
assegnato ciascun parametro passato allo script
( $1, $2, $3,…).
1.38
Operazioni sulle variabili
……
let “index += 5”
#incrementa
#index di 5
……
+=#incrementa la variabile
-= #decrementa la variabile
*= #moltiplica la variabile
/= #divide la variabile
1.39
la
variabile
Arrays
Nella shell bash, possiamo usare gli arrays. Il modo
più semplice per crearne uno è usare uno dei due
metodi seguenti:
pet[0]=dog
pet[1]=cat
pet[2]=fish
pet[4]=apple
pet=( dog cat fish apple )
Si possono inserire fino a 1024 elementi. Per
estrarre un valore, digitare ${arrayname[i]}.
$ echo ${pet[0]}
dog
$ echo ${pet[2]}
fish
1.40
Arrays
Per estrarre tutti gli elementi, usare un asterisco
come segue:
echo ${arraynames[*]}
Per vedere quanti elementi ci sono nell’array:
echo ${#arraynames[*]}
Si possono utilizzare gli arrays nei cicli per
realizzare la lista di un ciclo for:
for x in ${arrayname[*]}
do
echo $x
done
1.41
Un “for” alternativo
Una forma alternativa per la struttura for è
for (( EXPR1 ; EXPR2 ; EXPR3 ))
do
istruzioni
done
Per prima cosa, viene valutata l’espressione aritmetica
EXPR1. Quindi EXPR2 viene valutata ripetutamente fino a
che non assume risulta falsa. Ogni volta che EXPR2 è vera,
le istruzioni vengono eseguite e, in coda, viene eseguita
EXPR3.
1.42
Debugging
Bash fornisce due opzioni che danno informazioni utili per il
debugging:
-v : visualizza ciascuna linea dello script così come era stata digitata
prima dell’esecuzione;
-x : simile a sopra, ma se c’è un ciclo mostra tutti le iterazioni.
Utilizzo: #!/bin/bash –v, o #!/bin/bash –x
$ cat for3.sh
#!/bin/bash –x
echo –n “Enter a number: ”; read x
let sum=0
for (( i=1 ; $i<$x ; i=$i+1 )) ; do
let “sum = $sum + $i”
done
echo “the sum of the first $x numbers is: $sum”
1.43
Debugging
$ ./for3.sh
+ echo –n ‘Enter a number: ’
Enter a number: + read x
3
+ let sum=0
+ (( i=0 ))
+ (( 0<=3 ))
+ let ‘sum = 0 + 0’
+ (( i=0+1 ))
+ (( 1<=3 ))
+ let ‘sum = 0 + 1’
+ (( i=1+1 ))
+ (( 2<=3 ))
+ let ‘sum = 1 + 2’
+ (( i=2+1 ))
+ (( 3<=3 ))
+ let ‘sum = 3 + 3’
+ (( i=3+1 ))
+ (( 4<=3 ))
+ echo ‘the sum of the first 3 numbers is: 6’
the sum of the first 3 numbers is: 6
1.44
Dov’è l’errore?
Uno script da correggere
#!/bin/bash
# ex74.sh
a=37
if [$a -gt 27 ]
then echo $a
fi
Output dello script:
./ex74.sh: [37: command not found
1.45
Dov’è l’errore?
Uno script da correggere
#!/bin/bash -x
# ex74.sh
a=37
if [$a -gt 27 ]
then echo $a
fi exit
0
Output dello script:
+a=37
+’[37’ -gt 37 ‘]’
+ ./ex74.sh: [37: command not found
….
1.46
Il costrutto While
La struttura while è una struttura di ciclo che viene usata
per eseguire un insieme di comandi finchè una certa
condizione specificata è vera. Il ciclo termina non appena la
condizione diventa falsa. Se la condizione non diventa mai
falsa, il ciclo non termina e si entra in loop.
while espressione
do
istruzioni
done
1.47
Il costrutto continue
Il comando continue genera un salto all’iterazione
successiva del ciclo, dimenticando tutti i restanti comandi
in quella particolare iterazione.
#!/bin/bash
LIMIT=19
echo
echo “Printing Numbers 1 through 20 (but not 3
and 11)”
a=0
while [ $a -le “$LIMIT” ]; do
a=$(($a+1))
if [ “$a” -eq 3 ] || [ “$a” -eq 11 ]
then
continue
fi
echo -n “$a ”
done
1.48
Il costrutto break
Il comando break termina il ciclo (ed esce da esso).
#!/bin/bash
LIMIT=19
echo “Printing Numbers 1 through
something happens after 2 … ”
a=0
while [ $a -le “$LIMIT” ]; do
a=$(($a+1))
if [ “$a” -gt 2 ]
then
break
fi
echo -n “$a ”
done
echo; echo; echo
1.49
20,
but
Il costrutto until
La struttura until è molto simile alla struttura
while. La struttura until mantiene il ciclo
finchè la condizione è falsa. Quindi,
sostanzialmente, il significato è “finchè la
condizione è falsa, fai questo”.
until [espressione]
do
istruzioni
done
1.50
Manipolare le stringhe
Bash supporta un numero impressionante di operazioni per
manipolare stringhe. Sfortunatamente, questi strumenti non
soddisfano una delle primitive esigenze di Linux, cioè quella
dell’economicità dei comandi.
${#string} rende la lunghezza della stringa.
${string:position} estrae da $string la sottostringa che
inizia dalla posizione $position.
${string:position:length} estrae $length caratteri della
sottostringa di $string che inizia dalla posizione $position.
Esempio:
$ st=0123456789
$ echo ${#st}
10
$ echo ${st:6}
6789
$ echo ${st:6:2}
67
1.51
Sostituzione dei parametri
Manipolare e/o espandere variabili:
${parameter-default}, se “parameter” non è
istanziato, usa “default”.
$ echo ${username-”lferrari”}
lferrari
$ username=luca
$ echo ${username-”lferrari”}
luca
${parameter=default}, come sopra.
${parameter+value}, se “parameter” è istanziato,
usa value, altrimenti usa la stringa vuota.
$ echo ${username+andrea}
andrea
$ echo ${pippo+andrea}
# null string
1.52
Sostituzione dei parametri
${parameter?msg}, Se “parameter” è istanziato, lo
usa, altrimenti stampa msg.
$ value=${total?’total is not set’}
-bash: total: total is not set
$ total=10
$ value=${total?’total is not set’}
$ echo $value
10
Esempio:
#!/bin/bash
OUTFILE=symlinks.list
directory=${1-`pwd`}
for file in “$( find $directory -type l )”
do
echo “$file”
done | sort >> “$HOME/$OUTFILE”
1.53
Operazioni avanzate sulle stringhe
${string#substring},
elimina
la
più
corta
occorrenza corrispondente a substring dall’inizio di string.
pippo=abbcaabccbcabcdbcdaba
echo ${pippo#a*c}
# aabccbcabcdbcdaba
echo ${pippo##a*c}
# strips the longest
match
# daba
1.54
Operazioni avanzate sulle stringhe
${string/substring/replacement}, elimina la prima
occorrenza
corrispondente a
rimpiazzandola con replacement.
substring
in
string,
pippo=abbcaabccbcabcdbcdabab
echo ${pippo/ca/11}
# abb11abccbcabcdbcdabab
echo ${pippo//ca/11}
# abb11abccb11bcdbcdabab
# replaces all matches
echo ${pippo/[ab]?c/000}
# a000aabccbcabcdbcdabab
echo ${pippo/c*a/\!}
# abb!b
echo ${pippo//b?/00}
# a00caa00c00a00d00da00b
1.55
Funzioni
Le funzioni rendono gli scripts più facili da mantenere.
Sostanzialmente, permettono di suddividere il programma
in pezzetti più piccoli. Una funzione esegue un’azione
definita dall’utente, e può rendere un valore se l’utente lo
desidera.
#!/bin/bash
hello()
{
in
function
echo
“You
are
hello()”
}
echo “Calling function hello()…”
hello
echo “You are now out of function hello()”
Sopra, abbiamo richiamato la funzione hello() col suo
nome usando la linea: hello. Quando questa linea viene
eseguita, bash cerca nello script la linea hello(). La
trova, e ne esegue i contenuti.
1.56
Funzioni
#!/bin/bash
function check() {
if [ -e "/home/$1" ]
then
return 0
else
return 1
fi
}
echo “Enter the name of the file: ” ; read x
if check $x
then
echo “$x exists !”
else
echo “$x does not exist !”
fi.
1.57
Massimo comun divisore
#!/bin/bash
# gcd.sh: massimo comun divisore
# Si usa l’algoritmo di Euclide
# Il “massimo comun divisore" (gcd) di due interi è il più grande intero
# che divide entrambi, senza che ci sia del resto.
# L’algoritmo di Euclide utilizza divisioni successive.
# Ad ogni passo, dividend <--- divisor, divisor <--- remainder
# finchè remainder = 0. Nell’ultimo passo, si ha gcd = dividend.
ARGS=2 E_BADARGS=65
if [ $# -ne "$ARGS" ]
then
echo "Usage: `basename $0` first-number second-number"
exit $E_BADARGS
fi
1.58
Massimo comun divisore
gcd ()
{ dividend=$1
divisor=$2
remainder=1
until [ "$remainder" -eq 0 ] do
let "remainder = $dividend % $divisor"
dividend=$divisor
divisor=$remainder
done }
# Last $dividend is the gcd.
gcd $1 $2
echo; echo "GCD of $1 and $2 = $dividend“
1.59
Script 1: estrarre una carta a caso da un mazzo
#!/bin/bash
Suites=“Clubs Diamonds Hearts Spades”
Denominations=“2 3 4 5 6 7 8 9 10 Jack Queen King Ace”
# Read into array variable.
suite=($Suites)
denomination=($Denominations)
# Count how many elements.
num_suites=${#suite[*]}
num_denominations=${#denomination[*]}
# Extract
echo -n "${denomination[$((RANDOM%num_denominations))]}
of "
echo ${suite[$((RANDOM%num_suites))]}
1.60
Script 2: cambiare i nomi di tutti i file mettendoli in
lettere minuscole
#!/bin/bash
for filename in *
# Traverse all files in directory.
do
fname=`basename $filename`
# Change name to lowercase.
n=`echo $fname | tr A-Z a-z`
if [ “$fname” != “$n” ]
#
Rename
only
files
not
lowercase.
then
mv $fname $n
fi
1.61
done
already
Script 3: Confrontare due files con uno script
#!/bin/bash
ARGS=2 # Two args to script expected.
if [ $# -ne “$ARGS” ]; then
echo “Usage: `basename $0` file1 file2” ; exit 1
fi
if [ ! -r "$1“ ] || [ ! -r "$2" ] ; then
echo “Both files must exist and be readable.” ; exit
2
fi
cmp $1 $2 &> /dev/null
# /dev/null buries the output of the “cmp” command.
# Also works with 'diff', i.e., diff $1 $2 &> /dev/null
if [ $? -eq 0 ] # Test exit status of “cmp” command.
then
echo “File \“$1\” is identical to file \“$2\”.”
else
echo “File \“$1\“ differs from file \“$2\”.”
fi
1.62
Esercizio
#!/bin/bash
MAX=10000
for((nr=1; nr<$MAX; nr++)) do
let "t1 = nr % 5"
if [ "$t1" -ne 3 ]
then continue fi
let "t2 = nr % 7"
if [ "$t2" -ne 4 ]
then continue fi
let "t3 = nr % 9"
if [ "$t3" -ne 5 ]
then continue fi
break # What happens when you comment out this line? Why?
done
echo "Number = $nr"
exit 0
1.63