1 programmazione in shell the unix programming environment kernigham - pike
TRANSCRIPT
1
PROGRAMMAZIONE IN SHELL
The Unix Programming Environment
Kernigham - Pike
2
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
3
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
4
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
5
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> donerwxr-xr-x st909090 573 fileArwx------ st909090 200 fileB$ exit /* esce dalla shell e torna in csh */prompt>
6
Shell Script:
• oppure scrivere il programma in un shell script ed eseguirlo:for i in fileA fileBdols -l $idoneprompt> chmod a+x myscriptprompt> myscriptrwxr-xr-x st909090 573 fileArwx------ st909090 200 fileBprompt>
myscript
7
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)
8
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
9
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 sono automaticamente interpretati usando la shell
10
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
11
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>
12
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:>pathname=`pwd`
>echo $pathame
>/docsrv/gunetti `pwd`
apici
13
assegnazione di variabili da terminale
echo “inserire nome e cognome:”read nome cognomeecho “nome inserito = “ $nomeecho “cognome inserito = “ $cognome
prompt> myscriptinserire nome e cognome:Mario Rossinome inserito = Mariocognome inserito = Rossiprompt>
myscript
14
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
15
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
16
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.
17
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
18
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 quaquesto script si chiama myscript ed ha PID 16123
é stato chiamato con 3 argomenti
il secondo argomento é quo
é stato lanciato nella directory /docsrv/gunetti/tmp
19
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
20
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.
21
Il costrutto FOR
for var
do
comandi shell
done
• la variabile var assume come valore, in successione ad ogni ciclo, il nome degli argomenti passati in input.
prompt> myscript pippo pluto
myscript
22
Il costrutto FOR: esempio
for i
do
grep $i elenco_telefonico
done
prompt> cerca_elenco rossi bianchi
cerca_elenco
23
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
24
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 */
25
if-then-else:
if <lista1>
then <lista2>
[else <lista3>]
fi
• il ramo else é opzionale
• piú if-then-else possono essere nidificati
26
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
27
case
• Esecuzione in condizionale di piú alternative
case <var> in
<pattern_1>) <command_list_1>;;
.........
<pattern_n>) <command_list_n>;;
[*) <otherwise_command_list>;;]
esac
28
case - esempio:
read saluto
case $saluto in
ciao) echo “CIAO!”;
echo “Come stai?”;;
hello) echo “Hello!”;
echo “Come stai?”;;
*) echo “EMBÉ?”;;
esac
29
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
30
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”
31
until - do - Esempio:
who | grep $1 > tmpfile
until test ! -s tmpfile
do
echo “l’utente “ $1 “ é collegato”
sleep 60
who | grep $1 > tmpfile
done
echo “l’utente “ $1 “ non é collegato”
occhio alla negazione!
32
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.
33
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
34
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 $result5>• Occhio agli spazi!
35
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`