PROGRAMMAZIONE IN
SHELL
The Unix Programming Environment
Kernigham - Pike
1
Osservazioni generali
• I vari interpreti dei comandi che si possono
trovare su un sistema Unix (sh, csh, tcsh, ksh,
bsh) sono molto simili fra loro
• Tutti funzionano anche come linguaggi di
programmazione
• Tutti derivano dalla sh (shell) il primo
interprete scritto per il sistema Unix
• Il programma sh si trova su qualsiasi macchina
Unix, nella directory /bin
2
Osservazioni generali:
• Una sequenza di comandi shell puó essere data
direttamente al terminale una riga dopo l’altra:
prompt> ls -l <CR>
prompt> date <CR>
prompt> cp fileA fileB <CR>
• oppure scritta su un unica riga:
prompt> ls -l; date; cp fileA fileB <CR>
• oppure inserita in un file di comandi, che viene
detto: un Shell SCRIPT
3
Shell script
• un shell script puó essere eseguito con:
prompt> sh scriptfile
• oppure puó essere trasformato in un nuovo
comando del sistema rendendolo eseguibile:
prompt> chmod a+x scriptfile
prompt> scriptfile
• In ogni caso, il contenuto del file scriptfile viene
interpretato usando la shell. Se si vuole che sia
interpretato usando la csh bisogna aggiungere,
come prima riga del file:
#!/bin/csh
4
Shell Script:
• La stessa cosa vale se si usa la shell come
linguaggio di programmazione. Si puó lanciare un
programma shell in modo interattivo:
prompt> sh
/* entra in ambiente shell */
$ for i in fileA fileB
> do
> ls -l $i
> done
rwxr-xr-x
st909090 573 fileA
rwx-----st909090 200 fileB
$ exit
/* esce dalla shell e torna in csh */
prompt>
5
Shell Script:
• oppure scrivere il programma in un shell script ed
eseguirlo:
myscript
for i in fileA fileB
do
ls -l $i
done
prompt> chmod a+x myscript
prompt> myscript
rwxr-xr-x
st909090 573 fileA
rwx-----st909090 200 fileB
prompt>
6
Una directory di comandi personali
• La shell usa la variabile path settata nel file .cshrc
per stabilire in quali directory cercare i comandi
lanciati dall’utente.
• Ogni utente puó definire una propria directory di
comandi, e poi modificare la variabile path in
modo da lanciare i propri comandi senza
specificare ogni volta il loro pathname (cioé
proprio come se fossero un normale comando unix)
7
Una directory di comandi personali
• al fondo del file .cshrc inserire il comando:
set path=($path ~myloginname/mycommanddir)
/* aggiunge a path il nuovo pathname */
• Eseguire poi il comando:
source .cshrc /* rilegge il file .cshrc */
• Ora i comandi dentro mycommanddir possono
essere lanciati direttamente
• Attenzione: se aggiungete un nuovo file, perché sia
immediatamente attivo date il comando: rehash
8
Lavorare in ambiente shell
• ATTENZIONE: tutto quello che vedremo
funziona e si riferisce all’ambiente shell.
• Quando vi collegate al vostro account e usate un
qualsiasi terminale virtuale state usando la cshell
• Per usare la shell in modalitá interattiva dovete
entrare nell’ambiente shell lanciando: sh
• Per uscire dalla shell basta digitare dare il
comando exit e ritornate alla cshell
• Il problema non si pone se usate shell script, che
9
sono automaticamente interpretati usando la shell
Le variabili di shell
• La shell conosce un solo tipo di variabili:
stringhe di caratteri
• Il nome di una variabile shell puó essere una
qualsiasi sequenza di caratteri senza spazio e
metacaratteri non quotati
• Lo stesso ambiente shell definisce ed usa un
insieme di variabili per gestire correttamente la
connessione dell’utente
10
Le variabili di shell
• dando il comando env si possono vedere tutte le
variabili correntemente definite nell’ambiente di
lavoro.
• Per definire una nuova variabile shell basta
assegnarle un valore:
prompt> myvar=pippo /* ricordate: niente spazi! */
• per usare il valore di una variabile definita occorre
anteporle il simbolo $
prompt> echo $myvar
pippo
prompt>
11
Assegnamento dell’output di un
comando ad una variabile shell
• L’output di un comando puó essere assegnato ad
una variabile shell, e poi usato: apici
>pathname=`pwd`
>echo $pathame
>/docsrv/gunetti
`pwd`
12
assegnazione di variabili da terminale
echo “inserire nome e cognome:”
read nome cognome
echo “nome inserito = “ $nome
echo “cognome inserito = “ $cognome
myscript
prompt> myscript
inserire nome e cognome:
Mario Rossi
nome inserito = Mario
cognome inserito = Rossi
prompt>
13
Le variabili di shell
• Il valore di una variabile si usa direttamente:
prompt> myvar1=/etc/passwd
prompt> ls -l $myvar1
r-xr-xr-x root 4570 /etc/passwd
• Si puó concatenare ad un altro:
prompt> myvar2=.old
prompt> ls -l $myvar1$myvar2
r-xr-xr-x root 2620 /etc/passwd.old
14
Le variabili di shell
• Si puó concatenare una variabile ad una stringa
qualsiasi racchiudendo il nome della variabile tra
graffe o terminandolo con il back slash \:
prompt> myvar1=/etc/pass
prompt> ls -l ${myvar1}wd
r-xr-xr-x root 4570 /etc/passwd
• oppure:
prompt> ls -l $myvar1\wd.old
r-xr-xr-x root 2620 /etc/passwd.old
15
Le variabili di shell
• Peró non si puó concatenare una variabile ad una
stringa qualsiasi direttamente, perché quello
diventa un nuovo nome di variabile non definita:
prompt> myvar1=/etc/pass
prompt> more $myvar1wd
usage: more [...] [...] /*ERRORE nell’uso del more */
• Le variabili non definite hanno il valore della
stringa Null.
16
Alcune variabili predefinite:
•
•
•
•
•
•
•
$$: PID della shell corrispondente
$#: numero di argomenti di uno script shell
$0: nome dello script shell
$n: valore dell’ennesimo argomento dello script
$HOME: home directory dell’utente
$PWD: current working directory
$path: elenco delle directory in cui cercare i
comandi eseguiti
17
Script di uso delle variabili predefinite:
file myscript:
echo “questo script si chiama “ $0 “ ed ha PID = “ $$
echo “é stato chiamato con “ $# “argomenti”
echo “il secondo argomento é “ $2
echo “é stato lanciato nella directory “ $PWD
sh myscript qui quo qua
questo script si chiama myscript ed ha PID 16123
é stato chiamato con 3 argomenti
il secondo argomento é quo
é stato lanciato nella directory /docsrv/gunetti/tmp
18
Il costrutto FOR
for var in val_1 val_2 ... val_N
do
comandi shell
done
la variabile var assume in successione ad ogni ciclo,
i valori val_1, val_2, ..., val_N
19
Il costrutto FOR
for var in *
do
comandi shell
done
• la variabile var assume come valore, in
successione ad ogni ciclo, il nome degli oggetti
(file, sottodirectory) della directory corrente.
20
Il costrutto FOR
for var
do
comandi shell
done
myscript
• la variabile var assume come valore, in
successione ad ogni ciclo, il nome degli argomenti
passati in input.
prompt> myscript pippo pluto
21
Il costrutto FOR: esempio
for i
do
grep $i elenco_telefonico
done
cerca_elenco
prompt> cerca_elenco rossi bianchi
22
il comando TEST:
• test [-flag] espressione
• Restituisce true o false a seconda del tipo di test
e dell’espressione coinvolta.
• Viene usato in tutti i costrutti condizionali:
– if-then-else
– while-do
– until-do
• puó essere usato per testare variabili shell e file
23
il comando TEST:
• l’elenco completo dei flag é sul manuale. Esempi:
–
–
–
–
–
test s1 = s2 /* vero se s1=s2 - attenzione al blank */
test s1 != s2 /* vero se s1 diverso da s2 */
test s
/* vero se s non é la stringa vuota */
test -r file /* vero se file esiste ed é leggibile */
test -f file && test -s file /* vero se file é regolare e non
ha dimensione 0 -- || (doppia pipe) é l’or */
– test ! -s file /* vero se file e’vuoto -- ! é la negazione */
– test n1 -gt n2 /*vero se n1 é maggiore di n2 */
– test n1 -le n2 /* vero se n1 é minore o uguale a n2 */24
if-then-else:
if <lista1>
then <lista2>
[else <lista3>]
fi
• il ramo else é opzionale
• piú if-then-else possono essere nidificati
25
if-then-else - esempio:
var_A=ciao
var_B=hello
if test $1 = $var_A
then echo “Ciao! Come stai?”
else if test $1 = $var_B
then echo “hello! Come stai?”
else echo “non mi saluti?”
fi
fi
26
case
• Esecuzione in condizionale di piú alternative
case <var> in
<pattern_1>) <command_list_1>;;
.........
<pattern_n>) <command_list_n>;;
[*) <otherwise_command_list>;;]
esac
27
case - esempio:
read saluto
case $saluto in
ciao) echo “CIAO!”;
echo “Come stai?”;;
hello) echo “Hello!”;
echo “Come stai?”;;
*) echo “EMBÉ?”;;
esac
28
while - do / until - do
while <command>
do <command_list>
done
• Esegue il loop se <command> restituisce true
until <command>
do <command_list>
done
• Esegue il loop se <command> restituisce false
29
while - do - Esempio:
who | grep $1 > tmpfile
while test -s tmpfile /* tmpfile non é vuoto */
do
echo “l’utente “ $1 “ é collegato”
sleep 60
who | grep $1 > tmpfile
done
echo “l’utente “ $1 “ non é collegato”
30
until - do - Esempio:
who | grep $1 > tmpfile
occhio alla negazione!
until test ! -s tmpfile
do
echo “l’utente “ $1 “ é collegato”
sleep 60
who | grep $1 > tmpfile
done
echo “l’utente “ $1 “ non é collegato”
31
Selezione di porzioni di stringhe:
• cut -bX-Y filename
– taglia verticalmente filename prelevando per ogni
riga solo i caratteri dall’X-esimo all’Y-esimo
• echo “dipartimento” | cut -b3-7
– restituisce la stringa parti
• a=`who am i | cut -b1-4``hostname | cut -b1-4`
– setta la variabile a come la concatenazione dei
primi 4 caratteri del login e del nome dell’host.
32
Raggruppamento di comandi:
• ( lista di comandi )
– particolarmente utile per eseguire comandi in una
directory particolare specificata all’interno delle
parentesi:
(cd subdir; rm tmpfile)
al termine la directory corrente non é cambiata
33
Calcoli aritmetici: “expr”
expr <espressione aritmetica>
• expr premette di usare le variabili shell con
significato numerico, ed eseguire semplici calcoli:
>div=2
>result=`expr 10 / $div`
>echo $result
5
>
• Occhio agli spazi!
34
expr - Esempi:
Cont=10
while test $cont -gt 0
do
echo “cont = “ $cont
cont=`expr $cont - 1`
done
• l’uso di espressioni complesse è un pó goffo:
result=`expr “(“ 10 \* 5 “)” / 2`
35
Scarica

shell