MANUALE UNIX - I FILES BATCH
I FILE BATCH
Un
file batch in UNIX è un file testuale contenente una sequenza di
richiami a comandi UNIX o programmi.
L'obbiettivo dei files batch è l'automatizzazione di operazioni ripetitive.
Vediamo ora alcune istruzioni di base che ci consentiranno di costruire piccoli
programmi. Occorre precisare che le diverse shell presenti in ambito UNIX
implicano comandi differenti a secondo dell'interprete (shell) utilizzato.
Nel presente documento verranno analizzate le shell sh/bash e csh.
LE VARIABILI E GLI ARRAY
Le variabili servono a registrare dei valori acquisiti durante l'esecuzione di
un programma. L'inizializzazione di una variabile (assegnamento del valore
iniziale) avviene, a seconda della shell utilizzata, in modo differente:
- mediante il comando
SET
se utilizziamo la shell csh
- con un semplice assegnamento nel caso della shell
sh
ESEMPIO VAR 1
| Shell Sh - File setta.sh | Shell csh - file setta.csh |
# Inizializzazione
NOME="Marco"
# Stampa del valore
echo "Il mio NOME e': $NOME"
echo "Il mio nome e': $nome (le variabili sono CASE SENSITIVE)"
# Eliminazione della variabile
unset NOME
|
# Inizializzazione
set NOME="Marco"
# Stampa del valore
echo "Il mio NOME e': $NOME"
echo "Il mio nome e': $nome (le variabili sono CASE SENSITIVE)"
# Eliminazione della variabile
unset NOME
|
L'esecuzione dei due
script produce i seguenti output:
| Shell Sh - File setta.sh | Shell csh - file setta.csh |
sh-2.05# setta.sh sh: setta.sh: command not found sh-2.05# pwd /home/studente sh-2.05# echo $PATH /usr/local/bin:/bin:/usr/bin:/home/studente/bin sh-2.05# ./setta.sh sh: ./setta.sh: Permission denied sh-2.05# chmod 711 setta.sh sh-2.05# setta.sh sh: setta.sh: command not found sh-2.05# ./setta.sh Il mio NOME e': Marco Il mio nome e': (le variabili non sono CASE SENSITIVE) sh-2.05# ./setta.csh Il mio NOME e': Il mio nome e': (le variabili sono CASE SENSITIVE) |
[studente@localhost studente]# setta.csh setta.csh: Comando non trovato. [studente@localhost studente]# pwd /home/studente [studente@localhost studente]# echo $PATH /usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/bin:/home/studente/bin [studente@localhost studente]# ./setta.csh ./setta.csh: Permission denied. [studente@localhost studente]# chmod 711 setta.csh [studente@localhost studente]# setta.csh setta.csh: Comando non trovato. [studente@localhost studente]# ./setta.csh Il mio NOME e': Marco nome: Variabile non definita. [studente@localhost studente]# ./setta.sh NOME=Marco: Comando non trovato. NOME: Variabile non definita. |
si osservi che:
- per eseguire un file batch occorre fornire i diritti di esecuzione
necessari [
chmod 711 <nomefilebatch>
]
- se la cartella corrente non è nei percorsi registrati nella variabile
d'ambiente
PATH
è necessario anteporre
./ [cartella corrente]
al batch da eseguire
- il nome delle variabili è case sensitive:
NOME è una variabile differente da
nome.
- se eseguo lo script
in una shell differente da quella utilizzata per la progettazione si potrebbero verificare degli errori [vedremo
ora come risolvere questo ostacolo!]
Per eseguire uno script in una shell differente da quella usata nella
progettazione del file batch è necessario inserire all'inizio del file i
caratteri
#! seguiti dal percorso della shell che deve
interpretare i comandi ivi contenuti. Ecco gli esempi precedenti modificati
a tale scopo
| Shell Sh - File setta.sh | Shell csh - file setta.csh |
#!/bin/sh # Inizializzazione NOME="Marco" # Stampa del valore echo "Il mio nome e': $NOME" echo "Il mio nome e': $nome (le variabili sono CASE SENSITIVE)" # Eliminazione della variabile unset NOME |
#!/bin/csh -f # Inizializzazione set NOME="Marco" # Stampa del valore echo "Il mio nome e': $NOME" echo "Il mio nome e': $nome (le variabili sono CASE SENSITIVE)" # Eliminazione della variabile unset NOME |
I caratteri (#!), all'inizio dello script, informano il sistema che il file contiene una serie di comandi che devono essere eseguiti dall'interprete indicato dopo la sequenza #!. I caratteri #! rappresentano il magic number (due byte!) di un file batch unix. La sequenza #! identifica il tipo di file (in questo caso uno script di shell eseguibile!). Provate ad eseguite man magic per ottenere ulteriori dettagli in merito. Noterete che il magic number è utilizzato dal comando file per determinare il tipo di file. Immediatamente dopo #! compare un percorso: si tratta del percorso del programma che deve interpretare i comandi contenuti nello script. Questo programma può essere una shell, un linguaggio di programmazione o una utility (ad esempio awk). L'interprete quindi legge ed esegue i comandi dello script, partendo dall'inizio (la riga successiva a #!) ed ignorando gli eventuali commenti (#). Nella figura seguente vediamo l'esecuzione dei due batch scritti per shell differenti rispetto a quelle usate per l'esecuzione: come si nota funzionano!
| Shell Sh - esecuzione di setta.csh e setta.sh | Shell csh - esecuzione di setta.csh e setta.sh |
sh-2.05# ./setta.sh Il mio nome e': Marco Il mio nome e': (le variabili non sono CASE SENSITIVE) sh-2.05# ./setta.csh Il mio nome e': Marco nome: Variabile non definita. sh-2.05# file setta.sh setta.sh: Bourne shell script text executable sh-2.05# file setta.csh setta.csh: C shell script text executable |
[studente@localhost studente]# ./setta.sh Il mio nome e': Marco Il mio nome e': (le variabili non sono CASE SENSITIVE) [studente@localhost studente]# ./setta.csh Il mio nome e': Marco nome: Variabile non definita. [studente@localhost studente]# file setta.sh setta.sh: Bourne shell script text executable [studente@localhost studente]# file setta.csh setta.csh: C shell script text executable |
In UNIX è possibile definire anche degli array
(elenchi di valori recuperabili mediante un indice).
L'inizializzazione avviene con una scrittura differente a seconda della shell
- in sh gli array vengono definiti ad esempio in questo modo:
Colori=(rosso verde "blu di prussia" giallo magenta)
.
Il numero di elementi di un array può essere valutato utilizzando l'espressione
${#NomeArray[*]}
- in csh gli array vengono
definiti in modo leggermente differente. L'inizializzazione precedente diventa:
set Colori=(rosso verde "blu di prussia" giallo magenta).
Il numero di elementi di un array può essere valutato utilizzando l'espressione
$#NomeArray
ESEMPIO VAR 2
Vediamo ora un esempio di utilizzo degli array. Nell'esempio si utilizza il construtto iterativo while (ignoratelo per ora!) che analizzeremo più avanti.
| Shell Sh - File array.sh | Shell csh - file array.csh |
#!/bin/sh # Inizializzazione dell'array Colori=(rosso "blu di prussia" giallo) NrElementi=${#Colori[*]} echo "Ha $NrElementi colori. Sono:" i=0 while [ $i -lt $NrElementi ]; do echo "\$Colori[$i] = ${Colori[$i]}" let i++ done # Aggiungo altri elementi in coda Colori[${#Colori[*]}]="blu cobalto" Colori[${#Colori[*]}]=Nero NrElementi=${#Colori[*]} echo "Dopo ha $NrElementi colori. Sono:" let i=0 while [ $i -lt $NrElementi ]; do echo "\$Colori[$i] = $Colori[$i]" let i++ done |
#!/bin/csh -f # Inizializzazione array con valori senza spazi echo "----------------- ARRAY NOMI ---------------" set Nomi=(Mario Arturo Genoveffa) set NrElementi=$#Nomi echo "Ha $NrElementi Nomi. Sono:" $Nomi # Aggiunta di un nuovo elemento set Nomi=($Nomi "") set Nomi[$#Nomi]="Amilcare" set NrElementi=$#Nomi echo "Ha $NrElementi Nomi. Sono:" $Nomi # Inizializzazione array con valori con spazi echo "--------------- ARRAY COLORI ---------------" set Colori=(rosso "blu di prussia" giallo) set NrElementi=$#Colori echo "Ha $NrElementi colori. Sono:" $Colori # Creazione stringa contenente i valori dell'array # Ogni valore e' racchiuso da singolo apice ' set StrVal="" @ i=1 while ($i <= $NrElementi) set StrVal="$StrVal""'$Colori[$i]' " @ i++ end # Aggiunta di un nuovo elemento set StrVal="$StrVal""'Blu cobalto' " eval "set Colori = ($StrVal)" set StrVal="$StrVal""Nero " eval "set Colori = ($StrVal)" set NrElementi=$#Colori echo "Dopo ha $NrElementi colori. Sono:" @ i=1 while ($i <= $NrElementi) echo \$"Colori[$i] = $Colori[$i]" @ i++ end # Errore: Assegnamento out of range @ i = $#Colori + 1 set Colori[$i]="Verde" |
L'esecuzione dei due
script produce i seguenti output:
| Shell Sh - esecuzione di array.sh | Shell csh - esecuzione di array.csh |
sh-2.05# ./array.sh
Ha 3 colori. Sono:
$Colori[0] = rosso
$Colori[1] = blu di prussia
$Colori[2] = giallo
Dopo ha 5 colori. Sono:
$Colori[0] = rosso
$Colori[1] = blu di prussia
$Colori[2] = giallo
$Colori[3] = blu cobalto
$Colori[4] = Nero
|
[studente@localhost ~]$ ./array.csh [root@localhost ~]# ./leggi.csh ----------------- ARRAY NOMI --------------- Ha 3 Nomi. Sono: Mario Arturo Genoveffa Ha 4 Nomi. Sono: Mario Arturo Genoveffa Amilcare --------------- ARRAY COLORI --------------- Ha 3 colori. Sono: rosso blu di prussia giallo Dopo ha 5 colori. Sono: $Colori[1] = rosso $Colori[2] = blu di prussia $Colori[3] = giallo $Colori[4] = Blu cobalto $Colori[5] = Nero set: Indice fuori scala. |
si osservi che:
- la numerazione degli elementi in sh parte da 0 mentre in
csh parte da 1
- in sh/csh posso riferirmi al singolo elemento dell'array in questi due modi:
$Colori[$i] oppure
${Colori[$i]}
- in sh è possibile aggiungere nuovi elementi
dinamicamente in modo molto semplice:
Colori[${#Colori[*]}]="Nuovo colore"
- in csh gli array non si ridimensionano dinamicamente. Se
provo ad assegnare un valore ad un elemento fuori dal range ricevo
un errore {provate in una finestra csh a digitare la sequenza:
set x=(1 2 3);set x[4]=4.
Vedrete a video un messaggio di errore del tipo "indice fuori scala"}. Per aggiungere un nuovo
elemento occorre costruire una sequenza di istruzioni che ricopia tutti i valori contenuti
nell'array in una stringa
StrVal
facendo attenzione a
separare ogni valorizzazione con singoli apici (questo per evitare che
gli spazi presenti in un valore siano interpretati come separatori dando così
luogo a più valori).
Infine con le istruzioni
set StrVal="$StrVal""'Nuovo Valore' ";eval "set $Elenco=($strVal)"
ricreo ex novo
l'array accodando ai vecchi valori quello nuovo appena aggiunto. Quando l'array
da ridimensionare non
ha elementi (vedi parte iniziale dell'esempio array.csh con l'array nomi) con spazi nei valori
posso effettuare il ridimensionamento con
questa istruzione:
set Elenco=($Elenco "").
OPERATORI NUMERICI
Per effettuare degli assegnamenti numerici con
sh è
possibile utilizzare il comando built-in
let
oppure l'operatore
(())
Per la
csh
si usa l'operatore:
@
ESEMPIO OPERATORI 1
| Shell Sh - File operaz.sh | Shell csh - File operaz.csh |
let X=10 let Y=3 let Z=X+Y echo $X + $Y = $Z let Z=X-Y echo $X - $Y = $Z let Z=X*Y echo "$X * $Y = $Z" let Z=X**Y echo $X ^ $Y = $Z let Z=X/Y echo $X : $Y = $Z let Z=X%Y echo $X MOD $Y = $Z let A=8,3 let B=3,6 let C=A+B echo --------------------------------------------------- echo i comandi batch non gestiscono numeri decimali echo --------------------------------------------------- echo $A + $B = $C echo --------------------------------------------------- echo Se non delimito con \" posso avere degli errori se echo ho dei caratteri speciali nella stringa da stampare echo --------------------------------------------------- let C=A*B echo $A * $B = $C echo --------------------------------------------------- echo Per i caratteri speciali posso usare lo \\ davanti echo al carattere speciale echo --------------------------------------------------- echo $A \* $B = $C (( C = A ** B )) echo $A ^ $B = $C C=$(( A ** B )) echo $A ^ $B = $C (( A++, B-- )) echo successivo A:$A - precedente B:$B let "A = B + 1" echo A=B+1=$A |
#!/bin/csh -f @ X = 10 @ Y = 3 @ Z = $X + $Y echo $X + $Y = $Z @ Z = $X - $Y echo $X - $Y = $Z @ Z = $X * $Y echo "$X * $Y = $Z" @ Z = $X / $Y echo $X : $Y = $Z @ Z = $X % $Y echo $X MOD $Y = $Z @ Z = $X ^ $Y echo $X xor $Y = $Z @ X++ echo "X++ = " $X @ Y-- echo "Y-- = " $Y |
Questi script producono rispettivamente i seguenti output:
| Shell Sh - esecuzione di operaz.sh | Shell csh - esecuzione di operaz.csh |
sh-2.05# ./operaz.sh
10 + 3 = 13
10 - 3 = 7
10 * 3 = 30
10 ^ 3 = 1000
10 : 3 = 3
10 MOD 3 = 1
-----------------------------------------------
i comandi batch non gestiscono numeri decimali
-----------------------------------------------
8 + 3 = 11
---------------------------------------------------
Se non delimito con " posso avere degli errori se
ho dei caratteri speciali nella stringa da stampare
---------------------------------------------------
8 operaz 3 = 24
---------------------------------------------------
Per i caratteri speciali posso usare lo \ davanti
al carattere speciale
---------------------------------------------------
8 * 3 = 24
8 ^ 3 = 512
8 ^ 3 = 512
successivo A:9 - precedente B:2
A=B+1=3
|
[studente@localhost studente]# ./operaz.csh 10 + 3 = 13 10 - 3 = 7 10 * 3 = 30 10 : 3 = 3 10 MOD 3 = 1 10 xor 3 = 9 X++ = 11 Y-- = 2 |
Si osservi che nella shell sh:
- la divisione ammessa è quella intera
- non è possibile usare i decimali
- l'operatore ** (potenza) non è presente nelle prime shell
sh
- la stringa "$X * $Y = $Z" deve essere
racchiusa tra doppi apici altrimenti viene visualizzato un errore dovuto alla
presenza del carattere speciale *
- non posso inserire degli spazi nelle espressioni gestite con
let. In caso contrario devo racchiudere
l'espressione tra doppi apici
- scrivere
let x=x+1
è equivalente a
let "x = x + 1"
o a
((x = x +1)) o a
x=$((x+1))
o a
((x=x+1))
o a
((x++))
- all'interno dell'operatore
(())le
formule possono essere scritte utilizzando la stessa sintassi del C
- con l'operatore (()) posso eseguire
più operazioni separandole con la virgola
((x++,y--)).
Si osservi, relativamente alla shell csh che:
- dopo
#!/bin/csh
è possibile utilizzare le opzioni tipiche del comando csh:
-v
=> effettua l'echo dei comandi presenti nello script
-n
=> analizza la sintassi dello script ma non lo esegue
-f
=> esegue la csh più velocemente poichè non esegue il file di configurazione
$HOME/.cshrc.csh
-
non esiste l'operatore
Analizziamo ora gli operatori bit a bit presenti nella due shell analizzate:
| Operatori bit a bit - bash, sh e csh | |
| ^ | Bitwise XOR |
| | | Bitwise OR |
| & | Bitwise AND |
| ~ | Complemento a 1 |
| << | Bitwise left shift |
| >> | Bitwise right shift |
ESEMPIO OPERATORI 2
ecco un esempio dove vengono utilizzati questi operatori
| Shell Sh - File bitwise.sh | Shell csh - File bitwise.csh |
#!/bin/sh
let A=10
let B=7
echo "A=$A ; B=$B"
echo "In binario: A = 00001010"
echo " B = 00000111"
let C=$A^$B
echo "C=A^B = $C => (A XOr B) = 00001101"
let C=($A | $B)
echo "C=A|B = $C => (A Or B) = 00001111"
let C=($A & $B)
echo "C=A&B = $C => (A And B) = 00000010"
let C=~$A
echo "C=~A = $C => Bitwise Not(A) = 11110101"
echo " è il complemento a uno di A"
echo " 11110101 è il complemento a 2 di -11"
let C=($A<<3)
echo "C=(A<<3) = $C => shift a sinistra di 3 bit"
echo " (A >> B) = 01010000"
let C=($A>>1)
echo "C=(A>>1) = $C => shift a destra di 1 bit"
echo " (A >> B) = 00000101"
|
#!/bin/csh -f @ A=10 @ B=7 echo "A=$A ; B=$B" echo "In binario: A = 00001010" echo " B = 00000111" @ C = $A ^ $B echo "C=A^B = $C => (A XOr B) = 00001101" @ C = ($A | $B) echo "C=A|B = $C => (A Or B) = 00001111" @ C = ($A & $B) echo "C=A&B = $C => (A And B) = 00000010" @ C = ~($A) echo "C=~A = $C => Bitwise Not(A) = 11110101" echo " è il complemento a uno di A" echo " 11110101 è il complemento a 2 di -11" @ C = ($A<<3) echo "C=(A<<3) = $C => shift a sinistra di 3 bit" echo " (A >> B) = 01010000" @ C = ($A>>1) echo "C=(A>>1) = $C => shift a destra di 1 bit" echo " (A >> B) = 00000101" |
L'esecuzione dei due
script produce il medesimo output:
| Shell csh/sh - esecuzione di operaz.csh/sh |
[root@localhost ~]# ./bitwise.csh A=10 ; B=7 In binario: A = 00001010 B = 00000111 C=A^B = 13 => (A XOr B) = 00001101 C=A|B = 15 => (A Or B) = 00001111 C=A&B = 2 => (A And B) = 00000010 C=~A = -11 => Bitwise Not(A) = 11110101 è il complemento a uno di A 11110101 è il complemento a 2 di -11 C=(A<<3) = 80 => shift a sinistra di 3 bit (A >> B) = 01010000 C=(A>>1) = 5 => shift a destra di 1 bit (A >> B) = 00000101 |
si osserva:
- nella sh l'assegnamento non deve avere
spazi a meno che non si utilizzino le
()
o i doppi apici: "
- per evitare incomprensioni con i simboli speciali
<< , >> & |
si deve racchiudere l'espressione tra
()
- lo shift a destra (A >> n)
sposta i bit della rappresentazione binaria di
A a destra di
n
posizioni
- lo shift a sinistra (A << n) sposta i bit della rappresentazione binaria di
A a sinistra di
n posizioni
- La negazione a bit (complemento a 1) (~A)
ribalta la rappresentazione binaria di
A sostituendo gli uni con zero e viceversa
Analizziamo ora gli operatori di riassegnamento
| Operatori di riassegnamento | |||
| *= | A*=B | A=A*B | sh,csh |
| /= | A/=B | A=A/B | sh,csh |
| += | A+=B | A=A+B | sh,csh |
| -= | A-=B | A=A-B | sh,csh |
| %= | A%=B | A=A%B | sh,csh |
| ^= | A^=B | A=A^B | sh,csh |
| &= | A&=B | A=A&B | sh |
| |= | A|=B | A=A|B | sh |
| <<= | A<<=B | A=A<<B | sh |
| >>= | A>>=B | A=A>>B | sh |
ESEMPI OPERATORI 3
ecco un esempio in cui vengono utilizzati questi operatori
| Shell Sh - File reassign.sh | Shell csh - File reassign.csh |
#!/bin/sh
let A=10
let B=7
echo "A=$A ; B=$B"
let A*=$B
echo "A*=B ovvero A=A*B => $A ; B=$B"
let A/=$B
echo "A/=B ovvero A=A:B => $A ; B=$B"
let A%=$B
echo "A%=B ovvero A=RESTO(A,B) => $A ; B=$B"
let A+=$B
echo "A+=B ovvero A=A+B => $A ; B=$B"
let A-=$B
echo "A-=B ovvero A=A-B => $A ; B=$B"
let A^=$B
echo "A^=B ovvero A=A^B => $A ; B=$B"
let "A &= $B"
echo "A&=B ovvero A=A&B => $A ; B=$B"
let $((A |= $B))
echo "A|=B ovvero A=A|B => $A ; B=$B"
let $((A<<=3))
echo "A<<=3 ovvero A=A<<3 => $A"
let "A>>=3"
echo "A>>=3 ovvero A=A<<3 => $A"
|
#!/bin/csh -f
@ A=10
@ B=7
echo "A=$A ; B=$B"
@ A*=$B
echo "A*=B ovvero A=A*B => $A ; B=$B"
@ A/=$B
echo "A/=B ovvero A=A:B => $A ; B=$B"
@ A %= $B
echo "A%=B ovvero A=RESTO(A,B) => $A ; B=$B"
@ A+=$B
echo "A+=B ovvero A=A+B => $A ; B=$B"
@ A-=$B
echo "A-=B ovvero A=A-B => $A ; B=$B"
@ A^=$B
echo "A^=B ovvero A=A^B => $A ; B=$B"
|
| Shell sh - esecuzione di reassign.sh |
[root@localhost ~]# ./reassign.sh A=10 ; B=7 A*=B ovvero A=A*B => 70 ; B=7 A/=B ovvero A=A:B => 10 ; B=7 A%=B ovvero A=RESTO(A,B) => 3 ; B=7 A+=B ovvero A=A+B => 10 ; B=7 A-=B ovvero A=A-B => 3 ; B=7 A^=B ovvero A=A^B => 4 ; B=7 A&=B ovvero A=A&B => 4 ; B=7 A|=B ovvero A=A|B => 7 ; B=7 A<<=3 ovvero A=A<<3 => 56 A>>=3 ovvero A=A<<3 => 7 |
PASSAGGIO DI PARAMETRI
Come si citava all'inizio di questo prontuario un batchfile è un file testuale
nel quale sono inseriti dei comandi eseguibili. In unix è possibile progettare
un batchfile che legge gli argomenti digitati direttamente sulla linea di comando
(cioè scritti accanto al nome del file batch!).
ESEMPIO PARAMETRI 1
Si consideri un file batch
Somma
che effettua la
somma degli
argomenti passati sulla linea di comando. In altre parole quando digiterò ./Somma 1 23 12,
l'esecuzione del nostro batch dovrà restituire la somma degli argomenti (vedi figura
sottostante):
[studente@localhost studente]# ./Somma.sh 1 23 12 La somma 1 + 23 + 12 = 36 [studente@localhost studente]# |
lo script somma (in sh e csh) che
implementa l'esempio appena proposto (non viene gestito alcun controllo di
errore!) è il seguente:
| Shell Sh - File somma.sh | Shell csh - File somma.csh |
#!/bin/sh
if [ $# -eq 0 ]; then
echo "Nessun argomento: somma impossibile!"
else
let S=$1
echo -n $1
shift
for c
do
echo -n " + $c"
let S=S+c
done
echo " = $S"
fi
|
#!/bin/csh -f
@ S=0
if ($# == 0) then
echo "Nessun argomento: somma impossibile!"
goto Fine
endif
Inizio:
@ S = $S + $1
echo -n $1
shift
if ("$1" != "") then
echo -n " + "
goto Inizio
endif
echo " = $S"
Fine:
|
I parametri passati al batch sono leggibili tramite le variabili posizionali
$1 $2 ... $9, ${10}, ${11} ... ${!#}.
A queste si aggiungono:
- $#:
il numero di argomenti
- $0:
il nome del file batch file
- $*:
l'elenco completo dei parametri
(in sh posso usare
anche
$@
ma non con la shell csh)
-
${!#}: nella shell
sh è l'ultimo argomento passato.
-
$argv[!#]:
nella csh è l'ultimo argomento passato al file batch.
ESEMPIO PARAMETRI 2
Analizziamo l'esempio sottostante:
# Visualizzo i parametri
echo "Nome file batch : $0"
echo "Tutti i parametri : $*"
echo "Nr argomenti : $#"
echo "primo parametro : $1"
echo "secondo parametro : $2"
echo "terzo parametro : $3"
echo "quarto parametro : $4"
echo "quinto parametro : $5"
echo "sesto parametro : $6"
echo "settimo parametro : $7"
echo "ottavo parametro : $8"
echo "nono parametro : $9"
echo "decimo parametro : ${10}"
echo "undicesimo parametro : ${11}"
echo "dodicesimo parametro : ${12}"
echo "tredicesimo parametro : ${13}"
echo "quattordicesimo parametro : ${14}"
echo "quindicesimo parametro : ${15}"
echo "...."
echo "ultimo argomento (sh) : ${!#}"
#echo "ultimo argomento (csh) : $argv[$#]"
|
la sua esecuzione produce:
sh-2.05# ./elenca A B C D E F G H I L M N O P Q R S T U V Z Nome file batch : ./elenca Tutti i parametri : A B C D E F G H I L M N O P Q R S T U V Z Nr argomenti : 21 primo parametro : A secondo parametro : B terzo parametro : C quarto parametro : D quinto parametro : E sesto parametro : F settimo parametro : G ottavo parametro : H nono parametro : I decimo parametro : L undicesimo parametro : M dodicesimo parametro : N tredicesimo parametro : O quattordicesimo parametro : P quindicesimo parametro : Q .... ultimo argomento : Z sh-2.05# ./elenca A B Nome file batch : ./elenca Tutti i parametri : A B Nr argomenti : 2 primo parametro : A secondo parametro : B terzo parametro : quarto parametro : quinto parametro : sesto parametro : settimo parametro : ottavo parametro : nono parametro : decimo parametro : undicesimo parametro : dodicesimo parametro : tredicesimo parametro : quattordicesimo parametro : quindicesimo parametro : .... ultimo argomento : B |
Relativamente a questo esempio possiamo osservare:
- i doppi apici " consentono la conservazione esatta degli spazi inseriti nelle
frasi poste come argomento del comando echo
- se gli argomenti passati ad un batchfile sono in numero maggiore rispetto a quelli previsti
la sequenza in eccesso viene persa
- se gli argomenti passati al batchfile sono in numero minore rispetto a quelli previsti le
istruzioni predisposte per i parametri in eccesso vengono comunque eseguite. Per evitare l'inconveniente
occorre utilizzare l'istruzione, che analizzeremo più avanti, IF (ad esempio per evitare la stampa del 2°
parametro si può scrivere: if [ $# -ge 2 ];then echo "\$2="$2;fi oppure: if [ "$2" != "" ];then echo "\$2="$2;fi).
IL QUOTING
Per delimitare le stringhe si
possono usare i caratteri di quoting singoli (’) o doppi (").
ESEMPIO QUOTING 1
lo scripting seguente
#!/bin/sh
# con csh mettere
# set var=date
var=date
echo \$var ===\> $var
echo \"\$var\" =\> "$var"
echo \'\$var\' =\> '$var'
echo \`\$var\` =\> `$var`
echo \$\{var\} =\> ${var}
|
produce questo output
[studente@localhost studente]# ./quoting.sh $var ===> date "$var" => date '$var' => $var `$var` => ven apr 30 01:21:43 CEST 2010 ${var} => date |
Si osserva:
- il testo delimitato dal carattere ` (backquote o tick - ascii 96) viene eseguito
come se fosse un comando e al suo posto viene visualizzato
l'output generato.
- il singolo apice ' (ascii 39) interpreta la stringa letteralmente come se
fosse una sequenza di caratteri priva di qualsiasi significato particolare
(ad esempio non vengono rilevati e sostituiti i nomi delle variabili
presenti)
- Un
backslash (\) prima di un carattere indica al sistema che deve considerare quel
carattere letteralmente, senza assegnarli alcun significato speciale (esempio i
metacaratteri).
ESEMPIO QUOTING 2
Il
quoting può essere usato per separare una
variabile da una stringa fissa. Ad esempio si consideri la variabile
var,
a cui è stato assegnato il valore "bat", e la stringa costante "man".
Gli esempi successivi mostrano come combinare la variabile con la costante per ottenere come risultato la stringa "batman".
Si
noterà che l'istruzione
echo $varman non funzionerà, poichè la shell tenta di valutare una variabile
chiamata
varman, che però non esiste. Per ottenere il risultato desiderato si
deve separare opportunamente le stringhe, tramite il quoting oppure utilizzando le parentesi graffe
{}.
Ecco l'esempio utilizzando la shell sh:
#!/bin/sh
clear
# con csh mettere
# set var=bat
var=bat
echo CORRETTI:
echo \"\$var\"man =\> "$var"man
echo \$var\"man\" =\> $var"man"
echo \$\{var\}man =\> ${var}man
echo \$var\\man =\> $var\man
echo \$\{var\}man =\> ${var}man
echo \$var\"\"man =\> $var""man
echo ERRATI:
echo \\\$varman =\> \$varman
echo \`\$var\`man =\> `$var`man
echo \$var\`man\` =\> $var`man`
echo \{$\var\}man =\> {$var}man
|
che produce questo output
[studente@localhost studente]# ./quoting.sh CORRETTI: "$var"man => batman $var"man" => batman ${var}man => batman $var\man => batman ${var}man => batman $var""man => batman ERRATI: \$varman => $varman ./quoting.sh: bat: command not found `$var`man => man Quale pagina di guida vuoi? $var`man` => bat {$var}man => {bat}man [root@localhost studente]# [root@localhost studente]# man Quale pagina di guida vuoi? [root@localhost studente]# bat sh: bat: command not found |
Si osservi: INPUT ED OUTPUT Per quanto riguarda l'output
abbiamo visto che il comando
echo
visualizza a video il testo passato come argomento. Il comando
clear
consente di pulire completamente il video. Non esiste in unix un comando
equivalente all'
@ECHO
OFF
del dos visto che le shell unix non effettuano di default
l'echo dei comandi eseguiti in un batch file a meno che non si utilizzino
particolari opzioni della shell. Ad esempio in sh
per visualizzare i comandi eseguiti basta inserire come magic number #!/bin/sh -v
mentre in csh
#!/bin/csh -X.
l'esecuzione di questi script determina rispettivamente questi output
Uno schema riassuntivo per il comando
read
è la seguente
e lo script
incolonna.sh
seguente: si osservi: IF ELSE - ISTRUZIONE DI SELEZIONE Il construtto IF consente di replicare la
nostra capacità
selettiva ovvero "svolgo un'operazione basandomi su determinate condizioni".
- I caratteri
",
’,
\,
{
e
}
funzionano da delimitatori poichè non sono caratteri validi per il
nome di una variabile
- la stringa ’man’
viene eseguita come se fosse il richiamo al comando di help man
e al suo posto viene visualizzato il suo output: "Quale pagina di guida vuoi ?"
- la
variabile nella stringa
’$var’
viene sostituita con il suo valore bat ed in seguito eseguita
come se fosse un comando. Non essendo bat un comando
riconosciuto verrà visualizzato un messaggio di errore: "sh: bat: command
not found"
Ecco i caratteri di quoting (windows-1252)
34
DOPPIO APICE
"
39
SINGOLO APICE
'
96
ACCENTO GRAVE (BACKQUOTE)
`
145
APICE SINISTRO
‘
146
APICE DESTRO
’
147
DOPPIO APICE SINISTRO
“
148
DOPPIO APICE SINISTRO
”
180
ACCENTO ACUTO
´
L'input viene gestito in modo differente tra csh e sh:
In sh esiste il comando built-in read
che consente di acquisire ciò che viene digitato da tastiera. In csh per leggere
da tastiera si utilizza il comando: set variabile=$<.
ESEMPIO INPUT 1
Immaginiamo di dover leggere una frase da tastiera e di visualizzarla subito
dopo. Lo script
leggi,
nelle due shell in esame, potrebbe essere il seguente.
Shell Sh - File leggi.sh
Shell csh - File leggi.csh
#!/bin/sh
# \c: sequenza di escape che impedisce
# di andare a capo. Richiede l'opzione -e
# è equivalente a echo -n "Digita qualcosa: "
echo -e "Digita qualcosa: \c"
read INPUT
echo Hai digitato: $INPUT
#!/bin/csh -f
echo -n "Digita qualcosa ("\$\<" tra doppi apici): "
set INPUT="$<"
echo hai digitato $INPUT
echo -n "Digita qualcosa ("\$\<" senza doppi apici): "
set INPUT=$<
echo hai digitato $INPUT
Shell Sh
- esecuzione di leggi.sh
Shell csh - esecuzione di
leggi.csh
sh-2.05# ./leggi.sh
Digita qualcosa: AVE STUDENT
Hai digitato: AVE STUDENT
sh-2.05# ./leggi.sh
Digita qualcosa: AVE \STUDENT \
BUONO
Hai digitato: AVE STUDENT
[root@localhost ~]# ./leggi.csh
Digita qualcosa ($< tra doppi apici): AVE STUDENT
hai digitato AVE STUDENT
Digita qualcosa ($< senza doppi apici): AVE STUDENT
hai digitato AVE
[root@localhost ~]# ./leggi.csh
Digita qualcosa ($< tra doppi apici): AVE \
hai digitato AVE \
Digita qualcosa ($< senza doppi apici): AVE \
set: Il nome della variabile deve iniziare con una lettera.
Si osservi che:
- in sh inserendo uno \
in fondo alla linea è possibile leggere su più righe
-
gli invii non vengono inseriti nella variabile utilizzata dall'istruzione
read
- se con 'read'
(in sh) utilizzo l'opzione -r lo \
finale viene interpretato come un carattere
normale
- con una singola istruzione di
read si possono impostare più variabili. Basta
scrivere, dopo il comando
read, l'elenco delle variabili da leggere. Se, durante
l'esecuzione, si immettono meno valori (separati mediante spazio, tab o /)
rispetto al numero di variabili predisposte, le
rimanenti restano nulle. Se invece
si immettono più valori rispetto alle variabili impostate allora l'ultima
variabile acquisisce la parte restante fino all'invio (Ad esempio: se durante
l'esecuzione dell'istruzione: read INPUT1 INPUT2 digito AVE STUDENTE MODELLO
allora la variabile INPUT1 verrà valorizzata con la stringa
AVE mentre INPUT2
con la parte restante: STUDENTE MODELLO).
- in csh se non metto i doppi apici "$<" non posso
salvare in
una sola variabile una frase contenente degli spazi (esempio AVE STUDENT).
ESEMPIO INPUT 2
Scriviamo il seguente script
leggi_anagrafica.sh
read -r -p "Digita Cognome Nome e Provincia: " COGNOME NOME PROVINCIA
echo Cognome : $COGNOME
echo Nome : $NOME
echo Provincia : $PROVINCIA
ed analizziamo la sua esecuzione sotto la shell sh
[studente@localhost 5i]# ./leggi_anagrafica.sh
Digita Cognome Nome e Provincia: Sechi Marco /
Cognome : Sechi
Nome : Marco
Provincia : /
Si osservi che l'opzione -p consente di visualizzare la frase che spiega la
richiesta di input evitando così l'uso di echo iniziale
ESEMPIO INPUT 3
Opportune opzioni del comando
read consentono funzionalità simili a
quelle presenti nel comando
choice del dos.
read -s -t2 -n1 -p "Premi un tasto entro 2 secondi ..." tasto
if [ ! -z "$tasto" ]; then
echo; echo Hai premuto: $tasto
else
echo; echo "Tempo scaduto."
fi
Si osservi:
- l'opzione -s evita la visualizzazione del
carattere digitato
- l'opzione -t<secondi> indica il tempo entro il quale devo digitare qualcosa
- l'opzione -n<nr caratteri> indica quanti caratteri devo considerare nella lettura
ecco un esempio di esecuzione dello script appena
analizzato
[studente@localhost 5i]# ./attesa
Premi un tasto entro 2 secondi ...
Tempo scaduto.
[studente@localhost 5i]# ./attesa
Premi un tasto entro 2 secondi ...
Hai premuto: a
Opzioni
Significato
-a ANAME
Le parole digitate vengono salvate sequenzialmente
negli
elementi dell'array ANAME che cresce in modo dinamico. L'indice
dell'array parte da 0. Qualsiasi altra variabile passata al comando
read verrà ignorata.
Vediamo lo script d'esempio
Leggi_Elenco.sh
read -a ELENCO -p "Scrivi un elenco di nomi : "
let i=0
let N=${#ELENCO[*]}
while [ $i -lt $N ]
do
echo $(($i+1)) Nominativo: ${ELENCO[$i]}
let i=i+1
done
la cui esecuzione produce:
[root@localhost 5i]# ./Leggi_Elenco.sh
Scrivi un elenco di nomi : Paola Francesco Genoveffa
1 Nominativo: Paola
2 Nominativo: Francesco
3 Nominativo: Genoveffa
-d DELIM
Questa opzione consente di terminare un input con un carattere
differente dall'invio. Il delimitatore non verrà caricato nella
variabile utilizzata dal comando
read.
esempio
read -d\; -p "Scrivi qualcosa (termina con ;) : " INPUT
echo; echo $INPUT
read -d, -p "Scrivi qualcosa (termina con ,) : " INPUT
echo; echo $INPUT
l'esecuzione di questo script produce:
[root@localhost 5i]# ./leggi_terminatore.sh
Scrivi qualcosa (termina con ;) : Ciao
sono
io;
Ciao sono io
Scrivi qualcosa (termina con ,) : Ciao sono io,
Ciao sono io
-r
Raw mode. Con questa opzione il carattere
\ (backslash) non indica che l'input continua sulla riga
successiva (vedi esempio successivo opzione -e) ma viene interpretato come un
carattere normale
-e
Attivando questa opzione quando vado a capo con
\
la domanda viene ripetuta
read -p "Scrivi qualcosa (nessuna opzione): " INPUT
echo $INPUT
read -r -p "Scrivi qualcosa (opzione -r): " INPUT
echo $INPUT
read -e -p "Scrivi qualcosa (opzione -e) : " INPUT
echo $INPUT
l'esecuzione di questo script produce:
[root@localhost 5i]# ./prova_opzioni.sh
Scrivi qualcosa (nessuna opzione): prima \
seconda \
terza
prima seconda terza
Scrivi qualcosa (opzione -r): prima \
prima \
Scrivi qualcosa (opzione -e): prima \
Scrivi qualcosa (opzione -e): seconda \
Scrivi qualcosa (opzione -e): terza
prima seconda terza
-n NCHARS
read
termina dopo aver letto
NCHARS
caratteri
oppure appena batto invio. La variabile associata al comando
read
verrà inizializzata con al massimo
NCHARS
caratteri
-p PROMPT
Visualizza la frase di richiesta senza inserire un invio al termine.
-s
Silent mode. L'input non viene
visualizzato sul terminale
-tTIMEOUT
Imposta un timeout entro il quale l'utente deve digitare qualcosa.
Questa opzione non ha alcun effetto se l'istruzione
read
non sta
leggendo dal terminale o da una pipe
-u FD
Consente la lettura dal descrittore di file
FD.
- Attenzione! Tale opzione non è sempre presente in tutte le versioni sh. Lo
script
incolonna.sh sottostante ad esempio funziona nella Damn
SmallLinux ma non in RedHat 7.2 (ambienti utilizzati durante le lezioni).
si considerino due files:
PAOLA.TXT e
MARCO.TXT
MARCO.TXT
PAOLA.TXT
Nome: Marco
Alto: 1,72 mt
Peso: 78 kg
Capelli: Neri
Occhi: Marroni
Nome: Paola
Alto: 1,63 mt
Peso: 63 kg
Capelli: Rossi
Occhi: Verdi
Parentela: zia
while read -u3 f1 && read -u4 f2; do
echo -e "$f1\t$f2"
done 3<$1 4<$2
la sua esecuzione produce questo output:
[root@localhost 5i]# incolonna.sh MARCO.TXT PAOLA.TXT
Nome: Marco Nome: Paola
Alto: 1,72 mt Alto: 1,63 mt
Peso: 78 kg Peso: 63 kg
Capelli: Neri Capelli: Rossi
Occhi: Marroni Occhi: Verdi
- l'istruzione
3<$1
redirige il contenuto del file indicato nel 1° parametro sul file
identificato dal descrittore 3
- l'istruzione
4<$2
redirige il contenuto del file indicato nel 2° parametro sul file
identificato dal descrittore 4
- l'istruzione
read -u3 f1
legge la riga corrente sul file con descrittore 3 e la carica nella
variabile f1
- l'istruzione read -u4 f2
legge la riga corrente sul file con descrittore 4 e la carica nella
variabile f2
- con l'istruzione
while
il ciclo continua finché ho delle righe da leggere in entrambe i files (uso
l'operatore logico &&).
L'esecuzione si arresta quando arrivo in fondo ad uno dei due files
- l'&&
nel ciclo while assicura che la stampa avverrà solo quando
entrambe le righe sono state lette
In sh la sintassi della forma IF più compatta è la seguente:
if TEST-COMMANDS; then True-COMMANDS; else False-COMMANDS; fi
sh-2.05# echo $SHELL /bin/bash sh-2.05# if [ $SHELL == "/bin/bash" ]; then echo "Sei in una SH shell"; else echo "Sei nella shell: $SHELL"; fi Sei in una SH shell sh-2.05# if [ $SHELL == "/bin/csh" ]; then echo "Sei in una C-Shell"; else echo "Sei nella shell: $SHELL"; fi Sei nella shell: /bin/bash |
esiste una formulazione più estesa, che
riportiamo qui sotto, valida per le shell bash/sh:
|
if condizione1; then comandi da eseguire se la condizione1 è vera (true) [elif condizione2; then comandi da eseguire se la condizione2 è vera (true)] ... [elif condizioneN; then comandi da eseguire se la condizioneN è vera (true)] ... [else comandi da eseguire se tutte le precedenti condizioni sono false (false)] fi |
L'equivalente per la shell
csh
è la seguente
|
if (condizione1) then comandi da eseguire se la condizione1 è vera (true) [else if (condizione2) then comandi da eseguire se la condizione2 è vera (true)] ... [else if (condizioneN) then comandi da eseguire se la condizioneN è vera (true)] ... [else comandi da eseguire se tutte le precedenti condizioni sono false (false)] endif |
ESEMPIO IF 1
Il primo script di esempio
consente di valutare se quello che digito è un numero e, in caso affermativo, di valutare se si
tratta di un numero positivo, negativo oppure zero.
| Shell sh - File if.sh | Shell csh - file if.csh |
#!/bin/sh
unset STRINGA
read -p "Digita un numero: " STRINGA
let NUMERO=$STRINGA
if [ $NUMERO == $STRINGA ]; then
if [ $NUMERO -lt 0 ]; then
echo "$NUMERO: numero negativo"
elif [ $NUMERO -gt 0 ]; then
echo "$NUMERO: numero positivo"
else
echo "$NUMERO: zero"
fi
else
echo "$STRINGA NON E' UN NUMERO"
fi
|
#!/bin/csh -f
echo -n "Digita un numero: "
set STRINGA=$<
set NUMERO=`echo $STRINGA | awk '/^[\-,0-9]+$/'`
if ($NUMERO == $STRINGA) then
if ($NUMERO < 0) then
echo $NUMERO\: numero negativo
else if ($NUMERO > 0) then
echo $NUMERO\: numero positivo
else
echo $NUMERO\: Zero
endif
else
echo "$STRINGA NON E' UN NUMERO"
endif
|
Si osservi:
- in sh
l'istruzione [ espressione ] può essere sostituita con test espressione.
Test
espressione restituisce 0 se l'espressione è vera altrimenti 1 (falso)
-
l'istruzione set
NUMERO=`echo $STRINGA | awk '/^[\-,0-9]+$/'`
sostituisce l'istruzione @
NUMERO = $STRINGA poichè quest'ultima
visualizza un errore quando $STRINGA
non contiene un numero (l'utility
awk verrà illustrata in
dettaglio in seguito).
- si noti l'uso di \: nello script csh.
Infatti i : sono
il simbolo speciale: modificatore di variabile. Ecco degli esempi:
> esempio A sia
set A="/bin/bash/pippo.txt" allora:
A.1) [head] echo $A:h
visualizza /bin/bash
A.2) [tail]
echo $A:t visualizza pippo.txt
A.3) [extension] echo $A:e visualizza
txt
A.4) [root] echo $A:r visualizza /bin/bash/pippo
> esempio
B sia
set A=`ls` allora:
B.1) [all extension] echo $A:ge visualizza
l' elenco di tutte le estensioni dei files della cartella corrente.
Esistono
altri modificatori come gh, gr e gt)
Vediamo l'output prodotto dall'esecuzione di questi script
| Shell sh - esecuzione di if.sh | Shell csh - esecuzione di if.csh |
sh-2.05$ ./if.sh Digita un numero: 32 32: numero positivo sh-2.05$ ./if.sh Digita un numero: -21 -21: numero negativo sh-2.05$ ./if.sh Digita un numero: 0 0: zero sh-2.05$ ./if.sh Digita un numero: ca ca NON E' UN NUMERO |
[studente@localhost ~]$ ./if.csh Digita un numero: 21 21: numero positivo [studente@localhost ~]$ ./if.csh Digita un numero: -21 -21: numero negativo [studente@localhost ~]$ ./if.csh Digita un numero: 0 0: Zero [studente@localhost ~]$ ./if.csh Digita un numero: ca ca NON E' UN NUMERO |
Le condizioni utilizzate nell'IF sono costruite
utilizzando gli
OPERATORI DI CONFRONTO.
A seconda della shell e del tipo di dati questi operatori variano.
Vediamo quindi gli
operatori di confronto utilizzati per le
stringhe.
|
|
||||||||||||||||||||||||||||
ESEMPIO IF 2
Ecco alcuni esempi di utilizzo di questi operatori di confronto in
sh e
csh
| Shell sh - File str_relaz.sh | Shell csh - file str_relaz.csh |
#!/bin/sh
set -x +v
echo "---------------------------------------------------------"
echo "Se il batch e' corretto devono apparire solo "
echo "AFFERMAZIONI VERE"
echo "---------------------------------------------------------"
A=
# "$A" vera se $A e' non nulla (stringa vuota)
if [ "$A" ]; then
echo " 1.1) AFFERMAZIONE FALSA: \$A e' non nulla"
fi
# -z "$A" vera se $A se ha zero caratteri
if [ -z "$A" ]; then
echo " 2.1) AFFERMAZIONE VERA: \$A ha lunghezza zero {verifica: "${#A}"}"
fi
A="Studiare Info e' bellissimo"
# "$A" vera se $A e' non nulla (stringa vuota)
if [ "$A" ]; then
echo " 3.2) AFFERMAZIONE VERA : \$A e' non nulla"
fi
# -z "$A" vera se $A se ha zero caratteri
if [ -z "$A" ]; then
echo " 4.2) AFFERMAZIONE FALSA: \$A ha lunghezza zero {verifica: "${#A}"}"
fi
if [ -n "$A" ]; then
echo " 5.3) AFFERMAZIONE VERA: \$A ha "${#A}" caratteri"
fi
if [ "$A" == "Studiare Info e' bellissimo" ]; then
echo " 6.4) AFFERMAZIONE VERA: \$A e' uguale alla frase"
fi
if [ "$A" != "Studiare Info e' bellissimo" ]; then
echo " 7.3) AFFERMAZIONE FALSA: \$A e' diverso"
fi
if [ "$A" != "STUDIARE Info e' bellissimo" ]; then
echo " 8.5) AFFERMAZIONE VERA: \$A e' diverso"
fi
if [ "ABACO" \< "ZORRO" ]; then
echo " 9.6) AFFERMAZIONE VERA: ABACO < ZORRO"
fi
if [ "ZORRO" \> "ABACO" ]; then
echo "10.7) AFFERMAZIONE VERA: ZORRO > ABACO"
fi
if [ "6" \> "57" ]; then
echo "10.7) AFFERMAZIONE VERA: '6' > '57'"
fi
if [ 6 -lt 57 ]; then
echo "10.7) AFFERMAZIONE VERA: 6 < 57"
fi
|
#!/bin/csh -f
echo "---------------------------------------------------------"
echo "Se il batch è corretto devono apparire solo "
echo "AFFERMAZIONI VERE"
echo "---------------------------------------------------------"
set A= # otterrei lo stesso risultato con set A=""
# "$A" vera se $A e' non nulla (stringa vuota)
if ("$A" == "") then
echo " 1.1) AFFERMAZIONE VERA: "\$"A è la stringa vuota"
endif
if ("$A" != "") then
echo " 2.1) AFFERMAZIONE FALSA: "\$"A non è la stringa vuota"
endif
set A="Studiare Info è bellissimo"
if ("$A" == "") then
echo " 3.2) AFFERMAZIONE FALSA: "\$"A è la stringa vuota"
endif
if ("$A" != "") then
echo " 4.2) AFFERMAZIONE VERA: "\$"A non è la stringa vuota"
endif
if ( "$A" == "Studiare Info è bellissimo" ) then
echo " 5.3) AFFERMAZIONE VERA: "\$"A è uguale alla frase"
endif
if ( "$A" == "STUDIARE Info è bellissimo" ) then
echo " 6.3) AFFERMAZIONE FALSA: "\$"A è uguale alla frase"
endif
# "$A" =~ "Str" vera se $A contiene Str
if ( "$A" =~ *Anfo* ) then
echo " 7.4) AFFERMAZIONE FALSA: "\$"A contiene Anfo"
endif
if ( "$A" =~ *Info* ) then
echo " 8.4) AFFERMAZIONE VERA: "\$"A contiene Info"
endif
# "$A" !~ "Str" vera se $A non contiene Str
if ( "$A" !~ *Anfo* ) then
echo " 9.5) AFFERMAZIONE VERA: "\$"A non contiene Anfo"
endif
if ( "$A" !~ *Info* ) then
echo "10.5) AFFERMAZIONE FALSA: "\$"A non contiene Info"
endif
|
Si osservi che:
- se il valore della variabile contiene degli spazi è necessario, nella
condizione di test, racchiudere la variabile tra doppi apici. Infatti la sostituzione
della variabile con il suo valore determina nell'istruzione di test la creazione
di tanti argomenti
quante sono le parole separate dallo spazio e questo comporta la visualizzazione del seguente errore:
"if:
Errore di sintassi nell'espressione"
-
in sh l'istruzione
set -x
impone la
visualizzazione del valore contenuto nelle variabili mentre
set -v
la visualizzazione (echo) delle istruzioni
eseguite nel batch. In alternativa potevamo innserire queste opzioni
direttamente nel magic number
#!/bin/sh -x -v.
- Si ricordi che il confronto tra stringhe è differente da quello numerico. Ad
esempio la condizione
[ "6" \> "57" ]
è vera mentre
[ 6 -gt 57 ] è falsa.
- Gli operatori
<, >
si basano sul confronto lessicografico
- gli operatori
=~ , !~
non vogliono i "
Vediamo ora alcuni degli
operatori di test sui files con indicato a fianco le shell che li supportano
| Operatori di test sui file - bash, sh | ||
| -e file | vero se file esiste | sh,csh |
| -f file | vero se file è un file ordinario e non una cartella ne una device | sh,csh |
| -d file | vero se file è una cartella | sh,csh |
| -c file | vero se file è un device a caratteri | sh,csh |
| -b file | vero se file è un dispositivo a blocchi | sh,csh |
| -p file | vero se file è una named pipe | sh,csh |
| -S file | vero se file è un socket | sh,csh |
| -k file | vero se file ha il flag "sticky bit" (appiccicoso)attivo. [Un file con questo flag attivo, quando è eseguito viene mantenuto in memoria per consentire un avvio più rapido nelle riesecuzioni successive. Per le cartelle lo sticky bit assume un significato diverso: se un utente è in una cartella non sua ed ha i diritti di scrittura non potrà eliminare alcun file. Lo "Sticky bit" viene attivato con il comando chmod 1xxx nomefile oppure chmod +t nomefile. Al posto degli xxx useremo la tripla di numeri ottenuta come somma dei valori 0 (-) 1 (x) - 2 (w) e 4 (r) | sh,csh |
| -u file | vero se file ha il flag "set user-id" (suid) attivo. [Quando un file eseguibile, appartenente all'utente root, ha questo flag attivo verrà eseguito con i previlegi di amministratore anche se richiamato da un non superutente.] Lo "suid" flag è attivato con il comando chmod 4xxx nomefile oppure chmod u+s nomefile | sh,csh |
| -g file | vero se file ha il flag "set group-id" (sgid) attivo. [Quando una directory ha il flag "sgid" attivo allora un file creato al suo interno avrà come gruppo proprietario quello della cartella e non quello principale dell'utente che ha effettuato l'operazione]. Questa modalità risulta utile nelle cartelle condivise da un gruppo di utenti. Lo "sgid" flag è attivato con il comando chmod 2xxx nomefile oppure chmod g+s nomefile | sh,csh |
| -t FileDescriptor | vero se file descriptor è associato ad un terminale | sh,csh |
|
-r file -w file -x file |
vero se file è a sola lettura
per il proprietario vero se file è scrivibile per il proprietario vero se file è eseguibile per il proprietario |
sh,csh |
| file1 -ot file2 | vero se il file1 è più vecchio del file2 | sh |
| file1 -ef file2 | vero se il file1 e il file2 sono link allo stesso file | sh |
| file1 -nt file2 | vero se il file1 è più recente del file2 | sh |
| -O file | vero se l'utente collegato è il proprietario (owner) di file | sh |
| -G file | vero se il gruppo proprietario di file è uno dei gruppi a cui appartiene l'utente connesso. | sh |
| -h o -L file | vero se file è un link simbolico | sh |
| -N file | vero se file è stato modificato dopo l'ultima lettura | Non attivo in sh e csh di redhat 7.2 |
| -z file | vero se file esiste ed ha dimensione uguale a zero | csh |
| -s file | vero se file esiste ed ha dimensione maggiore di zero | sh,csh |
ESEMPIO IF 3.A
ecco un esempio di utilizzo degli operatori di
test sui files in sh
| Shell sh - File file_oper.sh |
echo -------------------------------------------
echo TEST sulla cartella /bin
echo -------------------------------------------
if [ -e /bin/ls ]; then
echo "A-1.1) AFFERMAZIONE VERA: /bin/ls esiste come file"
fi
if test -e /bin/sechi; then
echo "A-2.1) AFFERMAZIONE FALSA: /bin/sechi esiste come file"
fi
if test -d /bin; then
echo "A-3.2) AFFERMAZIONE VERA: /bin e' una cartella"
fi
if [ -d /bin/ls ]; then
echo "A-4.2) AFFERMAZIONE FALSA: /bin/ls e' una cartella"
fi
if [ -h /bin/sh ]; then
echo "A-5.3) AFFERMAZIONE VERA: /bin/sh è un link simbolico"
fi
if [ -f /bin/ls ]; then
echo "A-6.4) AFFERMAZIONE VERA: /bin/ls è un file ordinario (plain file)"
fi
if [ -s /bin/ls ]; then
echo "A-7.5) AFFERMAZIONE VERA: /bin/ls esiste ed ha dimensione maggiore di 0"
fi
# sh e bash2 sono dei link a /bin/bash
if [ /bin/sh -ef /bin/bash2 ]; then
echo "A-8.6) AFFERMAZIONE VERA: /bin/sh e /bin/bash2 sono link allo stesso file"
fi
# /bin/ps è del 28 agosto 2001 - /bin/ls è del 9 agosto 2001
if [ /bin/ps -ot /bin/ls ]; then
echo "A 9.3) AFFERMAZIONE FALSA: /bin/ps e' piu' vecchio di /bin/ls"
fi
if [ /bin/ps -nt /bin/ls ]; then
echo "A10.7) AFFERMAZIONE VERA: /bin/ps e' piu' recente di /bin/ls"
fi
echo -------------------------------------------
echo TEST sui file /dev
echo -------------------------------------------
if [ -b /dev/cdrom ]; then
echo "B-1.1) AFFERMAZIONE VERA: /dev/cdrom è una device a blocchi"
fi
if [ -c /dev/tty ]; then
echo "B-2.2) AFFERMAZIONE VERA: /dev/tty è una device a caratteri"
fi
if [ -f /dev/tty ]; then
echo "B-3.1) AFFERMAZIONE FALSA: /dev/tty è un file ordinario (plain file)"
fi
# /dev/initctl ha dimensione 0 ed è una named pipe
if [ -p /dev/initctl ]; then
echo "B-4.3) AFFERMAZIONE VERA: /dev/initctl e' una pipe FIFO"
fi
echo -------------------------------------------
echo TEST sui file /etc/httpd/conf/httpd.conf
echo "Diritti httpd.conf: " `ls -al /etc/httpd/conf/httpd.conf|cut -c 1-10`
echo -------------------------------------------
# attributi /etc/httpd/conf/httpd.conf: -rw-r--r--
if [ -r /etc/httpd/conf/httpd.conf ]; then
echo "C-1.1) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'"
echo " leggibile (per il proprietario)"
fi
if [ -w /etc/httpd/conf/httpd.conf ]; then
echo "C-2.2) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'"
echo " scrivibile (per il proprietario)"
fi
if [ -x /etc/httpd/conf/httpd.conf ]; then
echo "C-3.1) AFFERMAZIONE FALSA: /etc/httpd/conf/httpd.conf e'"
echo " eseguibile (per il proprietario)"
fi
if [ -O /etc/httpd/conf/httpd.conf ]; then
echo "C-4.3) AFFERMAZIONE VERA: l'utente collegato è proprietario"
echo " di /etc/httpd/conf/httpd.conf"
fi
if [ -G /etc/httpd/conf/httpd.conf ]; then
echo "C-5.4) AFFERMAZIONE VERA: un gruppo dell'utente collegato è "
echo " proprietario di /etc/httpd/conf/httpd.conf"
fi
echo -------------------------------------------
echo TEST su questo file batch: file.sh
echo -------------------------------------------
# l'utente collegato è root ma il proprietario
# è studente
if [ -O /home/studente/file.sh ]; then
echo "D-1.1) AFFERMAZIONE FALSA: l'utente collegato è "
echo " proprietario di /home/studente/file.sh"
fi
chgrp root /home/studente/file.sh
if [ -G /home/studente/file.sh ]; then
echo "D-2.1) AFFERMAZIONE VERA: un gruppo dell'utente collegato è"
echo " proprietario di /home/studente/file.sh"
fi
chmod 0000 /home/studente/file.sh
echo "Diritti con 0000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10`
if [ -k /home/studente/file.sh ]; then
echo "D-3.2) AFFERMAZIONE FALSA: /home/studente/file.sh ha settato lo sticky bit"
fi
if [ -g /home/studente/file.sh ]; then
echo "D-4.3) AFFERMAZIONE FALSA: /home/studente/file.sh ha settato lo sgid bit"
fi
if [ -u /home/studente/file.sh ]; then
echo "D-5.4) AFFERMAZIONE FALSA: /home/studente/file.sh ha settato lo suid bit"
fi
chmod 1000 /home/studente/file.sh
echo "Diritti con 1000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10`
if [ -k /home/studente/file.sh ]; then
echo "D-6.2) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sticky bit"
fi
chmod 2000 /home/studente/file.sh
echo "Diritti con 2000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10`
if [ -g /home/studente/file.sh ]; then
echo "D-7.3) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sgid bit"
fi
chmod 4000 /home/studente/file.sh
echo "Diritti con 4000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10`
if [ -u /home/studente/file.sh ]; then
echo "D-8.4) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo suid bit"
fi
echo -------------------------------------------
echo TEST sui files descriptor
echo -------------------------------------------
if [ -t 0 ]; then
echo "E-1) Questo messaggio non si vede se scrivo: file_oper.sh < input.txt"
fi
if [ -t 1 ]; then
echo "E-2) Questo messaggio non si vede se scrivo: file_oper.sh > output.txt"
fi
if [ -t 2 ]; then
echo "E-3) Questo messaggio non si vede se scrivo: file_oper.sh 2> stderr.txt"
fi
echo -------------------------------------------
echo TEST vari
echo -------------------------------------------
# Azzero il file
cat /dev/null > /home/studente/ciao
# ----------------------------------------------
# nella shell di RedHat 7.2 questo Test non
# è supportato: if [ -z /home/studente/ciao ]; then
# possiamo usare il negato del test -s
# ----------------------------------------------
if [ ! -s /home/studente/ciao ]; then
echo "F-3.3) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione uguale a 0"
fi
echo "Accodo questa frase" >> /home/studente/ciao
if [ -s /home/studente/ciao ]; then
echo "F-4.4) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione maggiore di 0"
fi
|
ESEMPIO IF 3.B
ed ecco l'esempio di utilizzo degli operatori di
test sui files in csh
| Shell csh - file str_relaz.csh |
#!/bin/csh echo "-------------------------------------------" echo "TEST sulla cartella /bin" echo "-------------------------------------------" if ( -e /bin/ls ) then echo "A-1.1) AFFERMAZIONE VERA: /bin/ls esiste come file" endif if ( -e /bin/sechi ) then echo "A-2.1) AFFERMAZIONE FALSA: /bin/sechi esiste come file" endif if ( -d /bin ) then echo "A-3.2) AFFERMAZIONE VERA: /bin e' una cartella" endif if ( -d /bin/ls ) then echo "A-4.2) AFFERMAZIONE FALSA: /bin/ls e' una cartella" endif if ( -f /bin/ls ) then echo "A-5.3) AFFERMAZIONE VERA: /bin/ls è un file ordinario (plain file)" endif if ( -s /bin/ls ) then echo "A-6.4) AFFERMAZIONE VERA: /bin/ls esiste ed ha dimensione maggiore di 0" endif echo ------------------------------------------- echo TEST sui file /dev echo ------------------------------------------- if ( -b /dev/cdrom ) then echo "B-1.1) AFFERMAZIONE VERA: /dev/cdrom è una device a blocchi" endif if ( -c /dev/tty ) then echo "B-2.2) AFFERMAZIONE VERA: /dev/tty è una device a caratteri" endif if ( -f /dev/tty ) then echo "B-3.1) AFFERMAZIONE FALSA: /dev/tty è un file ordinario (plain file)" endif # /dev/initctl ha dimensione 0 ed è una named pipe if ( -p /dev/initctl ) then echo "B-4.3) AFFERMAZIONE VERA: /dev/initctl e' una pipe FIFO" endif echo ------------------------------------------- echo TEST sui file /etc/httpd/conf/httpd.conf echo "Diritti httpd.conf: " `ls -al /etc/httpd/conf/httpd.conf|cut -c 1-10` echo ------------------------------------------- # attributi /etc/httpd/conf/httpd.conf: -rw-r--r-- if ( -r /etc/httpd/conf/httpd.conf ) then echo "C-1.1) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'" echo " leggibile (per il proprietario)" endif if ( -w /etc/httpd/conf/httpd.conf ) then echo "C-2.2) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'" echo " scrivibile (per il proprietario)" endif if ( -x /etc/httpd/conf/httpd.conf ) then echo "C-3.1) AFFERMAZIONE FALSA: /etc/httpd/conf/httpd.conf e'" echo " eseguibile (per il proprietario)" endif echo ------------------------------------------- echo TEST su questo file batch: file.sh echo ------------------------------------------- # l'utente collegato è root ma il proprietario # è studente chmod 0000 /home/studente/file.sh echo "Diritti con 0000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10` if ( -k /home/studente/file.sh ) then echo "D-1.1) AFFERMAZIONE FALSA: /home/studente/file.sh ha settato lo sticky bit" endif if ( -g /home/studente/file.sh ) then echo "D-2.2) AFFERMAZIONE FALSA: /home/studente/file.sh ha settato lo sgid bit" endif if ( -u /home/studente/file.sh ) then echo "D-3.3) AFFERMAZIONE FALSA: /home/studente/file.sh ha settato lo suid bit" endif chmod 1000 /home/studente/file.sh echo "Diritti con 1000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10` if ( -k /home/studente/file.sh ) then echo "D-4.1) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sticky bit" endif chmod 2000 /home/studente/file.sh echo "Diritti con 2000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10` if ( -g /home/studente/file.sh ) then echo "D-5.2) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sgid bit" endif chmod 4000 /home/studente/file.sh echo "Diritti con 4000 di /home/studente/file.sh: " `ls -al /home/studente/file.sh|cut -c 1-10` if ( -u /home/studente/file.sh ) then echo "D-6.3) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo suid bit" endif echo ------------------------------------------- echo TEST sui files descriptor echo ------------------------------------------- if ( -t 0 ) then echo "E-1) Questo messaggio non si vede se scrivo: file_oper.csh < input.txt" endif if ( -t 1 ) then echo "E-2) Questo messaggio non si vede se scrivo:" echo " file_oper.csh >& stderr.txt" echo " file_oper.csh > output.txt" endif if ( -t 2 ) then echo "E-3) Questo messaggio non si vede se scrivo:" echo " file_oper.csh >& stderr.txt" endif echo ------------------------------------------- echo TEST vari echo ------------------------------------------- # Azzero il file cat /dev/null > /home/studente/ciao if ( -z /home/studente/ciao ) then echo "F-1.1) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione uguale a 0" endif if ( -s /home/studente/ciao ) then echo "F-2.1) AFFERMAZIONE FALSA: /home/studente/ciao esiste e ha dimensione uguale a 0" endif echo "Accodo questa frase" >> /home/studente/ciao if ( -z /home/studente/ciao ) then echo "F-3.2) AFFERMAZIONE FALSA: /home/studente/ciao esiste e ha dimensione maggiore di 0" endif if ( -s /home/studente/ciao ) then echo "F-4.2) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione maggiore di 0" endif |
l'esecuzione di questi script produce i seguenti output
| Shell Sh - esecuzione di if.sh | Shell csh - esecuzione di if.csh |
sh-2.05# ./file_test.sh
-------------------------------------------
TEST sulla cartella /bin
-------------------------------------------
A-1.1) AFFERMAZIONE VERA: /bin/ls esiste come file
A-3.2) AFFERMAZIONE VERA: /bin e' una cartella
A-5.3) AFFERMAZIONE VERA: /bin/sh è un link simbolico
A-6.4) AFFERMAZIONE VERA: /bin/ls è un file ordinario (plain file)
A-7.5) AFFERMAZIONE VERA: /bin/ls esiste ed ha dimensione maggiore di 0
A-8.6) AFFERMAZIONE VERA: /bin/sh e /bin/bash2 sono link allo stesso file
A10.7) AFFERMAZIONE VERA: /bin/ps e' piu' recente di /bin/ls
-------------------------------------------
TEST sui file /dev
-------------------------------------------
B-1.1) AFFERMAZIONE VERA: /dev/cdrom è una device a blocchi
B-2.2) AFFERMAZIONE VERA: /dev/tty è una device a caratteri
B-4.3) AFFERMAZIONE VERA: /dev/initctl e' una pipe FIFO
-------------------------------------------
TEST sui file /etc/httpd/conf/httpd.conf
Diritti httpd.conf: -rw-r--r--
-------------------------------------------
C-1.1) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'
leggibile (per il proprietario)
C-2.2) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'
scrivibile (per il proprietario)
C-4.3) AFFERMAZIONE VERA: l'utente collegato è proprietario
di /etc/httpd/conf/httpd.conf
C-5.4) AFFERMAZIONE VERA: un gruppo dell'utente collegato è
proprietario di /etc/httpd/conf/httpd.conf
-------------------------------------------
TEST su questo file batch: file.sh
-------------------------------------------
D-2.1) AFFERMAZIONE VERA: un gruppo dell'utente collegato è
proprietario di /home/studente/file.sh
Diritti con 0000 di /home/studente/file.sh: ----------
Diritti con 1000 di /home/studente/file.sh: ---------T
D-6.2) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sticky bit
Diritti con 2000 di /home/studente/file.sh: ------S---
D-7.3) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sgid bit
Diritti con 4000 di /home/studente/file.sh: ---S------
D-8.4) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo suid bit
-------------------------------------------
TEST sui files descriptor
-------------------------------------------
E-1) Questo messaggio non si vede se scrivo: file_oper.sh < input.txt
E-2) Questo messaggio non si vede se scrivo: file_oper.sh > output.txt
E-3) Questo messaggio non si vede se scrivo: file_oper.sh 2> stderr.txt
-------------------------------------------
TEST vari
-------------------------------------------
F-3.3) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione uguale a 0
F-4.4) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione maggiore di 0
|
[root@localhost ~]# ./file_test.csh
-------------------------------------------
TEST sulla cartella /bin
-------------------------------------------
A-1.1) AFFERMAZIONE VERA: /bin/ls esiste come file
A-3.2) AFFERMAZIONE VERA: /bin e' una cartella
A-5.3) AFFERMAZIONE VERA: /bin/ls è un file ordinario (plain file)
A-6.4) AFFERMAZIONE VERA: /bin/ls esiste ed ha dimensione maggiore di 0
-------------------------------------------
TEST sui file /dev
-------------------------------------------
B-1.1) AFFERMAZIONE VERA: /dev/cdrom è una device a blocchi
B-2.2) AFFERMAZIONE VERA: /dev/tty è una device a caratteri
B-4.3) AFFERMAZIONE VERA: /dev/initctl e' una pipe FIFO
-------------------------------------------
TEST sui file /etc/httpd/conf/httpd.conf
Diritti httpd.conf: -rw-r--r--
-------------------------------------------
C-1.1) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'
leggibile (per il proprietario)
C-2.2) AFFERMAZIONE VERA: /etc/httpd/conf/httpd.conf e'
scrivibile (per il proprietario)
-------------------------------------------
TEST su questo file batch: file.sh
-------------------------------------------
Diritti con 0000 di /home/studente/file.sh: ----------
Diritti con 1000 di /home/studente/file.sh: ---------T
D-4.1) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sticky bit
Diritti con 2000 di /home/studente/file.sh: ------S---
D-5.2) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo sgid bit
Diritti con 4000 di /home/studente/file.sh: ---S------
D-6.3) AFFERMAZIONE VERA: /home/studente/file.sh ha settato lo suid bit
-------------------------------------------
TEST sui files descriptor
-------------------------------------------
E-1) Questo messaggio non si vede se scrivo: file_oper.csh < input.txt
E-2) Questo messaggio non si vede se scrivo:
file_oper.csh >& stderr.txt
file_oper.csh > output.txt
E-3) Questo messaggio non si vede se scrivo:
file_oper.csh >& stderr.txt
-------------------------------------------
TEST vari
-------------------------------------------
F-1.1) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione uguale a 0
F-4.2) AFFERMAZIONE VERA: /home/studente/ciao esiste e ha dimensione maggiore di 0
|
Gli
operatori di confronto numerici in sh e
csh sono:
sh
csh
Operatori di confronto numerici
-eq
==
UGUALE
-ne
!=
DIVERSO
-lt
<
MINORE
-le
<=
MINORE E UGUALE
-gt
>
MAGGIORE
-ge
>=
MAGGIORE O UGUALE
Le diverse condizioni possono essere legate tra
loro tramite gli operatori logici AND, OR, NOT
|
|
||||||||||||||||
ESEMPIO IF 4.A -
AND:
per controllare che due o più condizioni siano soddisfatte dobbiamo utilizzare
l'operatore logico AND.
L'esempio proposto controlla che un punto (x,y) stia nel primo quadrante del
piano cartesiano (origine inclusa).
![]() |
Shell sh - File AND.sh | Shell csh - File AND.csh |
read -p "Digita X:" X read -p "Digita Y:" Y # In alternativa a [ expr ] posso usare (( expr )) # if (( $X >= 0 && $Y >= 0 )); then if [ $X -ge 0 -a $Y -ge 0 ]; then echo "($X,$Y) E' NEL PRIMO QUADRANTE" else echo "($X,$Y) NON E' NEL PRIMO QUADRANTE" fi |
#!/bin/csh -f echo -n "Digita X:";set X=$< echo -n "Digita Y:";set Y=$< if ( $X >= 0 && $Y >= 0 ) then echo "($X,$Y) E' NEL PRIMO QUADRANTE" else echo "($X,$Y) NON E' NEL PRIMO QUADRANTE" endif |
ESEMPIO IF 4.B -
OR:
per verificare che tra diverse condizioni almeno una condizione sia soddisfatta
occorre utilizzare l'operatore logico OR.
L'esempio proposto controlla che un punto (x,y) sia
esterno al primo quadrante del piano cartesiano.
![]() |
Shell sh - File OR.sh | Shell csh - File OR.csh |
read -p "Digita X:" X read -p "Digita Y:" Y # In alternativa a [ expr ] posso usare (( expr )) # if (( $X < 0 || $Y < 0 )); then if [ $X -lt 0 -o $Y -lt 0 ]; then echo "($X,$Y) NON E' NEL PRIMO QUADRANTE" else echo "($X,$Y) E' NEL PRIMO QUADRANTE" fi |
#!/bin/csh -f echo -n "Digita X:";set X=$< echo -n "Digita Y:";set Y=$< if ( $X < 0 || $Y < 0 ) then echo "($X,$Y) NON E' NEL PRIMO QUADRANTE" else echo "($X,$Y) E' NEL PRIMO QUADRANTE" endif |
ESEMPIO IF 4.C -
NOT:
![]() |
Shell sh - File NOT.sh | Shell csh - File NOT.csh |
#!/bin/sh read -p "Digita X:" X read -p "Digita Y:" Y # In alternativa a [ expr ] posso usare (( expr )) # if !(( $X < 0 || $Y < 0 )); then if ! [ $X -lt 0 -o $Y -lt 0 ]; then echo "($X,$Y) E' NEL PRIMO QUADRANTE" else echo "($X,$Y) NON E' NEL PRIMO QUADRANTE" fi |
#!/bin/csh -f echo -n "Digita X:";set X=$< echo -n "Digita Y:";set Y=$< if !( $X >= 0 && $Y >= 0 ) then echo "($X,$Y) NON E' NEL PRIMO QUADRANTE" else echo "($X,$Y) E' NEL PRIMO QUADRANTE" endif |
GOTO - ISTRUZIONE DI SALTO
L' istruzione GOTO, presente solo in csh, consente di saltare con l'esecuzione ad un altro punto dello script. La sintassi generica è la seguente
GOTO Etichetta
ESEMPIO GOTO 1
In questo esempio viene stampata la sequenza dei primi 10 numeri interi.
| Shell csh - file goto.csh |
#!/bin/csh -f @ i=1 inizio: echo -n "$i " @ i++ if ( $i <= 10 ) goto inizio echo "Fine" |
CASE - ISTRUZIONE DI SELEZIONE MULTIPLA
L' istruzione
CASE consente di selezionare una sequenza di esecuzione controllando
N condizioni. La sintassi
generica è la seguente
| Sintassi CASE in bash o sh | Sintassi CASE in csh |
|
case variabile in pattern1.0 [|pattern1.1] ... ) comando1.1 ... command1.K1 ;; [pattern2.0 [|pattern2.1] ... ) comando2.1 ... command2.K2 ;; ... patternJ.0 [|patternJ.1] ... ) comandoJ.1 ... commandJ.Kj ;; ... * ) comandoN.1 ... commandN.KN ;;] esac |
switch(variabile) pattern1.0: [pattern1.1]: ...: comando1.1 ... command1.K1 breaksw pattern2.0: [pattern2.1]: ...: comando2.1 ... command2.K2 breaksw ... patternJ.0: [patternJ.1]: ...: comandoJ.1 ... commandJ.KJ breaksw ... default: comandoN.1 ... commandN.KN endsw |
Questa costrutto può essere
sostituito con questa sequenza
IF ELSE:
| Sintassi IF equivalente al CASE in bash o sh | Sintassi IF equivalente al CASE in csh |
|
if condizione1; then comando1.1 ... command1.K1 [elif condizione2; then comando2.1 ... command2.K2 ... [else comandoN.1 ... commandN.KN fi |
if
(condizione1) then comando1.1 ... command1.K1 [else if (condizione2) then comando2.1 ... command2.K2 ... [else comandoN.1 ... commandN.KN endif |
ESEMPIO CASE 1
L'esempio seguente valuta il tipo di carattere premuto. Ecco due
script: il primo in sh
e il secondo, equivalente, in csh
| Shell sh - File case.sh |
read -n1 -r -p "digita un tasto: " Tasto
echo;
case "$Tasto" in
# [[:upper:]] ) echo "Hai digitato: $Tasto :-> Lettera MAIUSCOLA";;
[A-Z] ) echo "Hai digitato: $Tasto :-> Lettera MAIUSCOLA";;
# [[:lower:]] ) echo "Hai digitato: $Tasto :-> Lettera Minuscola";;
[a-z] ) echo "Hai digitato: $Tasto :-> Lettera minuscola";;
[0-9] ) echo "Hai digitato: $Tasto :-> un numero";;
"*" | "+" | "-" | "/" | "^" ) echo "Hai digitato: $Tasto :-> Operatore aritmetico";;
# oppure: [\*+\-\/^] ) ... ;;
[\{\}\[\]\(\)] ) echo "Hai digitato: $Tasto :-> Parentesi";;
# oppure: "{"|"}"|"("|")"|"["|"]" ) ... ;;
* ) echo "Altro";;
esac
|
| Shell csh - file case.csh |
#!/bin/csh -f
echo -n "digita un tasto: "
set Tasto = `head -1`
switch ("$Tasto")
case [a-z]:
echo "Hai digitato: $Tasto :-> Lettera minuscola"
breaksw
case [A-Z]:
echo "Hai digitato: $Tasto :-> Lettera MAIUSCOLA"
breaksw
case [0-9]:
echo "Hai digitato: $Tasto :-> Un numero"
breaksw
case ")":
case "(":
case "]":
case "}":
case "{":
case [\[]:
echo "Hai digitato: $Tasto :-> Parentesi"
breaksw
case [\*+/\^-]:
# O in alternativa
# case "+":
# case "-":
# case "/":
# case [\*]:
# case \^:
echo "Hai digitato: $Tasto :-> Operatore aritmetico"
breaksw
default:
echo "Altro"
endsw
|
si osservi che:
- nel case della csh i : non devono essere
preceduti da spazi.
- Più condizioni abbinate devono essere scritte su linee distinte
- nello script sh la condizione [A-Z] è stata scritta per prima
poichè,
nella versione di RedHat 7.2 utilizzata per le prove, la sequenza
[a-z] accetta sia le lettere maiuscole che minuscole
- si osservi la modalità alternativa per l'input proposta nell'esempio csh
(ma è applicabile anche in sh) basata sull'istruzione set Tasto
= `head -1` che consente la lettura di una frase fino all'invio. Nel
caso si voglia leggere solo il primo carattere della stringa di input digitata
si può utilizzare il comando: set Tasto
= `head --bytes=1`.
L'esecuzione dei due script fornisce i seguenti output
| Shell Sh - esecuzione di case.sh | Shell Csh - esecuzione di case.csh |
sh-2.05$ ./case.sh
digita un tasto: a
Hai digitato: a :-> Lettera minuscola
sh-2.05$ ./case.sh
digita un tasto: A
Hai digitato: A :-> Lettera MAIUSCOLA
sh-2.05$ ./case.sh
digita un tasto: 1
Hai digitato: 1 :-> un numero
sh-2.05$ ./case.sh
digita un tasto: (
Hai digitato: ( :-> Parentesi
sh-2.05$ ./case.sh
digita un tasto: )
Hai digitato: ) :-> Parentesi
sh-2.05$ ./case.sh
digita un tasto: {
Hai digitato: { :-> Parentesi
sh-2.05$ ./case.sh
digita un tasto: }
Hai digitato: } :-> Parentesi
sh-2.05$ ./case.sh
digita un tasto: [
Hai digitato: [ :-> Parentesi
sh-2.05$ ./case.sh
digita un tasto: ]
Hai digitato: ] :-> Parentesi
sh-2.05$ ./case.sh
digita un tasto: +
Hai digitato: + :-> Operatore aritmetico
sh-2.05$ ./case.sh
digita un tasto: *
Hai digitato: * :-> Operatore aritmetico
sh-2.05$ ./case.sh
digita un tasto: -
Hai digitato: - :-> Operatore aritmetico
sh-2.05$ ./case.sh
digita un tasto: /
Hai digitato: / :-> Operatore aritmetico
sh-2.05$ ./case.sh
digita un tasto: ^
Hai digitato: ^ :-> Operatore aritmetico
sh-2.05$ ./case.sh
digita un tasto: !
Altro
sh-2.05$ ./case.sh
digita un tasto: $
Altro
|
[studente@localhost ~]$ ./case.csh
digita un tasto: a
Hai digitato: a :-> Lettera minuscola
[studente@localhost ~]$ ./case.csh
digita un tasto: A
Hai digitato: A :-> Lettera MAIUSCOLA
[studente@localhost ~]$ ./case.csh
digita un tasto: 1
Hai digitato: 1 :-> Un numero
[studente@localhost ~]$ ./case.csh
digita un tasto: {
Hai digitato: { :-> Parentesi
[studente@localhost ~]$ ./case.csh
digita un tasto: }
Hai digitato: } :-> Parentesi
[studente@localhost ~]$ ./case.csh
digita un tasto: )
Hai digitato: ) :-> Parentesi
[studente@localhost ~]$ ./case.csh
digita un tasto: (
Hai digitato: ( :-> Parentesi
[studente@localhost ~]$ ./case.csh
digita un tasto: ]
Hai digitato: ] :-> Parentesi
[studente@localhost ~]$ ./case.csh
digita un tasto: [
Hai digitato: [ :-> Parentesi
[studente@localhost ~]$ ./case.csh
digita un tasto: +
Hai digitato: + :-> Operatore aritmetico
[studente@localhost ~]$ ./case.csh
digita un tasto: -
Hai digitato: - :-> Operatore aritmetico
[studente@localhost ~]$ ./case.csh
digita un tasto: *
Hai digitato: * :-> Operatore aritmetico
[studente@localhost ~]$ ./case.csh
digita un tasto: /
Hai digitato: / :-> Operatore aritmetico
[studente@localhost ~]$ ./case.csh
digita un tasto: ^
Hai digitato: ^ :-> Operatore aritmetico
[studente@localhost ~]$ ./case.csh
digita un tasto: $
Altro
[studente@localhost ~]$ ./case.csh
digita un tasto: !
Altro
|
ecco gli script equivalenti scritti con il construtto if
| Shell sh - File ifcase.sh | Shell sh - File ifcase.csh |
#!/bin/sh
read -n1 -r -s -p "premi un tasto: " Tasto
echo ""
if [ "\\$Tasto" = "\*" ]; then
echo "Hai digitato: $Tasto :-> Operatore aritmetico"
elif [ -z `echo $Tasto|tr -d 'a-z'` ]; then
echo "Hai digitato: $Tasto :-> Lettera minuscola"
elif [ -z `echo $Tasto|tr -d 'A-Z'` ]; then
echo "Hai digitato: $Tasto :-> Lettera MAIUSCOLA"
elif [ -z `echo $Tasto|tr -d '0-9'` ]; then
echo "Hai digitato: $Tasto :-> Un numero"
elif [ -z `echo $Tasto|tr -d '\{\}\[\]\(\)'` ]; then
echo "Hai digitato: $Tasto :-> Parentesi"
elif [ -z `echo $Tasto|tr -d '+\-\/^'` ]; then
echo "Hai digitato: $Tasto :-> Operatore aritmetico"
else
echo "Altro"
fi
|
#!/bin/csh -f
echo -n "digita un tasto: "
set Tasto = `head --bytes=1`
if ( `echo "$Tasto"|tr -d "{}[]()"` == "" ) then
echo "Hai digitato: $Tasto :-> Parentesi"
else if ( `echo "$Tasto"|tr -d '\*+\-\/^'` == "" ) then
echo "Hai digitato: $Tasto :-> Operatore aritmetico"
else if ( "$Tasto" =~ [a-z]) then
echo "Hai digitato: $Tasto :-> Lettera minuscola"
else if ( "$Tasto" =~ [A-Z]) then
echo "Hai digitato: $Tasto :-> Lettera MAIUSCOLA"
else if ( "$Tasto" =~ [0-9]) then
echo "Hai digitato: $Tasto :-> Un numero"
else
echo "Altro"
endif |
Si osservi che il comando tr (translate) con l'opzione -d elimina da una stringa le lettere indicate, pertanto l'istruzione echo $Tasto | tr -d 'caratteri' elimina dalla variabile $Tasto tutti i caratteri indicati nella stringa 'caratteri'
FOR - ISTRUZIONE ITERATIVA
La sintassi del comando for è la seguente
| Sintassi FOR in bash o sh | Sintassi FOREACH in csh |
for variabile [in Insieme] do IstruzioneFOR [break] [continue] done |
foreach variabile (Insieme) IstruzioneFOR [break] [continue] end |
L'istruzione break interrompe il ciclo for e l'esecuzione prosegue con
l'istruzione successiva a done (sh)/ end (csh). L'istruzione continue interrompe
l'iterazione corrente e l'esecuzione riprende con l'iterazione successiva.
L
| Shell sh - File pianeti.sh |
#!/bin/sh for Pianeti in Mercurio Venere Terra Marte "Fascia degli Asteroidi" Giove Saturno Urano Nettuno Plutone do echo $Pianeti done |
Ecco l'esempio equivalente scritto con la shell csh
| Shell csh - File pianeti.csh |
#!/bin/csh -f foreach Pianeti (Mercurio Venere Terra Marte "Fascia degli Asteroidi" Giove Saturno Urano Nettuno Plutone) echo $Pianeti end |
Si osservi l'uso dei doppi apici " nel caso un valore presenti al suo
interno degli spazi.
ESEMPIO FOR 2
Se la parte
[in Insieme]
in sh viene omessa allora il FOR
utilizza come elenco di valori
quelli scritti sulla linea dil comando dopo il nome del batch. In csh il comando equivalente
richiede invece l'uso della variabile speciale $*
Shell sh - File args.sh
Shell csh - file args.csh
#!/bin/sh
for c; do echo $c; done
#!/bin/csh -f
foreach c ( $* )
echo $c
end
ESEMPIO FOR 3
L'insieme
analizzato dal for può essere generato
con l'output di un comando.
Nell'esempio successivo vengono rielaborati (in sh) tutti
i files che iniziano per
L della
cartella di sistema /bin.
| Shell sh - File File_L.sh |
for c in `ls /bin/l*`; do echo $c; done |
Ecco due esempi in csh che svolgono la stessa funzione di
File_L.sh.
Nelle parentesi del foreach di csh
è possibile scrivere o il comando (delimitato dal backquote) oppure il solo argomento utilizzato nel comando
| Shell csh - File File_L.csh | |
#!/bin/csh -f foreach c (/bin/l*) echo $c end |
#!/bin/csh -f foreach c (`ls /bin/l*`) echo $c end |
| Shell sh - File ContaFile.sh |
let N=0 for i in `ls -R / 2>/dev/null | grep .txt$`; do let N=N+1; done echo $N Files di testo let N=0 for i in `((ls -R / 3>&2 2>&1 >&3) 2>/dev/null)|cut -c 1` do let N=N+1 done echo $N Files non accessibili |
L'equivalente in csh
è il seguente
[si ricordi che la
ridirezione >& ridirige sia
lo stdout che lo stderr - quindi per simulare la separazione tra
stderr e stdout in csh
occorre scrivere qualcosa del tipo: (comando > fileOut) >& fileErr ]:
| Shell sh - File ContaFile.csh |
#!/bin/csh -f @ N=0 foreach i (`(((ls -R / > pippo) >& /dev/null); grep .txt$ pippo)`) @ N++ end echo $N Files di testo @ N=0 foreach i (`(ls -R / >/dev/null) |& cut -c 1`) @ N++ end echo $N Files non accessibili |
Ecco un esempio di esecuzione
| Shell Sh - esecuzione di ContaFile.sh | Shell csh - esecuzione di ContaFile.csh |
sh-2.05$ whoami studente sh-2.05$ ./ContaFile.sh 542 Files di testo 76 Files non accessibili sh-2.05$ su -s /bin/sh root Password: sh-2.05# ./ContaFile.sh 542 Files di testo 0 Files non accessibili sh-2.05# |
[studente@localhost ~]$ whoami studente [studente@localhost ~]$ ./ContaFile.csh 542 Files di testo 76 Files non accessibili [studente@localhost ~]$ su -s /bin/csh root Password: [studente@localhost studente]# ./ContaFile.csh 542 Files di testo 0 Files non accessibili [studente@localhost studente]# |
ESEMPIO FOR 5
In quest'altro esempio vengono conteggiate tutte le cartelle e i files presenti
nel nostro sistema [si ricordi che:
find
<path> -type d
=> elenca le directory,
find <path> -type f
=> elenca i files,
find <path> -type l
=> elenca i link simbolici]
| Shell sh - File ContaDIrFile.sh |
let N=0 let F=0 for i in `find / -type d 2>/dev/null|cut -c 1`; do let N=N+1; done for i in `find / -type f 2>/dev/null|cut -c 1`; do let F=F+1; done echo $N Cartelle - $F Files |
ed ecco la soluzione scritta in csh
| Shell sh - File ContaDIrFile.csh |
#!/bin/csh -f @ N=0 @ F=0 foreach i (`(find / -type d) |& grep -v "Permission denied" | cut -c 1`) @ N++ end foreach i (`(find / -type f) |& grep -v "Permission denied" | cut -c 1`) @ F++ end echo $N Cartelle - $F Files |
In sh esiste anche un'altra sintassi per il for molto simile a quella usata i c++:
| Sintassi alternativa del FOR in bash o sh |
|
for ((contatore=ValoreIniziale, Contatore Relazione ValoreFinale ; Passo) do IstruzioneFOR [break] [continue] done |
ESEMPIO FOR 6
Ecco due script equivalenti che stampano la sequenza dei numeri dispari da 1 a 10
[1 3 5 7 9]
| Shell sh - File Iteraz.sh | Shell sh - File Iteraz2.sh |
let N=10
for ((a=1; a <= N ; a++))
do
if [ $(($a%2)) -eq 0 ]; then
continue
fi
echo -n "$a "
done
echo;
|
for ((a=1; ; a++)) do if [ $(($a%2)) -eq 0 ]; then continue ; fi if [ $a -gt 10 ]; then break ; fi echo -n "$a " done echo; |
Si osservi che:
-
L'istruzione
continue
termina il ciclo corrente e l'esecuzione prosegue con l'iterazione successiva
partendo da a++
-
L'istruzione
break termina il ciclo for corrente e prosegue con l'istruzione successiva a done
WHILE - Istruzione Iterativa
La sintassi del comando While è la seguente:
| Sintassi WHILE in bash o sh | Sintassi WHILE in csh |
while [CondizioneVera] do IstruzioneWHILE [break] [continue] done |
while (CondizioneVera) IstruzioneWHILE [break] [continue] end |
ESEMPIO WHILE 1
Il primo esempio stampa tutti gli argomenti passati ad un programma batch
(si ricordi che
$#
indica il numero di argomenti passati al batch file)
| Shell sh - File elenca.sh | Shell csh - file elenca.csh |
#!/bin/sh while [ $# -gt 0 ] do echo $1 shift done |
#!/bin/csh -f while ($#argv != 0 ) echo $argv[1] shift end |
| Shell sh - File while_RND.sh |
Massimo=80 N=0 Numero=$(($RANDOM%100)) while [ $Numero -lt $Massimo ] do let N++ echo -n "$N^) $Numero " Numero=$(($RANDOM%100)) done echo;echo "Ho generato $N numeri inferiori a $Massimo - Ultimo: $Numero" |
ed ecco il suo equivalente in csh. Si noti che in csh non esiste la variabile d'ambiente $RANDOM per cui per generare un numero casuale sfrutto l'ambiente offerto dal comando awk.
| Shell sh - File WHILE_digita.csh |
#!/bin/csh -f
@ Massimo=80
@ N=0
@ Numero=`awk 'BEGIN {srand();x=sprintf("%d",rand()*100); print x}'`
while ($Numero < $Massimo)
@ N++
echo -n "$N^) $Numero "
@ Numero=`awk 'BEGIN {srand();x=sprintf("%d",rand()*100); print x}'`
end
echo;echo "Ho generato $N numeri inferiori a $Massimo - Ultimo: $Numero"
|
ESEMPIO WHILE 3
il seguente script richiede di digitare qualcosa finchè non si digita
fine
| Shell sh - File WHILE_digita.sh |
Frase=""
while [ "$Frase" != "Fine" ]
do
read -p "Digita qualcosa (Fine per uscire) >> " Frase
if [ "$Frase" != "Fine" ]; then
echo "Hai digitato: $Frase"
else
echo "Programma terminato!"
fi
done
|
ed ecco il suo equivalente in csh
| Shell sh - File WHILE_digita.csh |
#!/bin/csh -f
set Frase=""
while ( "$Frase" != "Fine" )
echo -n "Digita qualcosa (Fine per uscire) >> : "
set Frase=$<
if ( "$Frase" != "Fine" ) then
echo "Hai digitato: $Frase"
else
echo "Programma terminato!"
endif
end
|
in sh esiste un'altro construtto iterativo: until. Contrariamente al while il loop termina quando la condizione diventa vera:
| Sintassi UNTIL in csh |
Until [CondizioneFalsa] do IstruzioneUNTIL done |
ESEMPIO UNTIL 1
il programma precedente con
until
diventa:
| Shell sh - File UNTIL_Digita.sh |
Frase=""
until [ "$Frase" == "Fine" ]
do
read -p "Digita qualcosa (Fine per uscire) >> " Frase
if [ "$Frase" != "Fine" ]; then
echo "Hai digitato: $Frase"
else
echo "Programma terminato!"
fi
done
|
FUNCTION
Nella shell sh è possibile definire delle funzioni. La sintassi per le funzioni è la seguente (si noti l'assenza della dichiarazione degli argomenti):
| Sintassi Function in sh | Sintassi alias |
function NomeFunzione {
IstruzioneFUNZIONE
}
oppure
NomeFunzione() {
IstruzioneFUNZIONE
} |
alias NomeAlias 'Comando' |
Nella csh non esistono le funzioni ma è possibile costruire qualcosa di simile
con il comando alias
| Shell sh - File funzione.sh | Shell csh |
# La dichiarazione della funzione deve essere
# fatta prima della sua chiamata
Scrivi ()
{
echo "Scrivo qualcosa"
echo "Ora esco da \"Scrivi()\"."
}
# Esempio di chiamata funzione.
# Scrivi
|
[root@localhost ~]# alias Scrivi 'echo "Scrivo qualcosa";echo "Ora esco da "\""Scrivi"\""."' [root@localhost ~]# Scrivi Scrivo qualcosa Ora esco da "Scrivi". [root@localhost ~]# alias calcola '@ z = (\!*) ; echo $z' [root@localhost ~]# calcola 1 + 2 * 7 15 [root@localhost ~]# |
Le funzioni sono come dei mini-scripts: possono accettare dei parametri,
usano delle variabili locali e restituiscono dei valori agli script chiamanti.
Le funzioni interpretano i parametri in modo posizionale. Il nome dei
parametri posizionali è lo stesso visto per quelli usati negli script batch
ovvero $#, $*, $0, $1... .
Nel comando alias
(csh) le seguenti stringhe indicano:
- \!*
: l'elenco dei parametri passati
(corrisponde alla variabile sh $*),
- \!$
: l'ultimo parametro
(corrisponde alla variabile sh ${!#}),
-
\!:1 o \!^
: il primo parametro
(corrisponde a $1),
-
\!!
: l'intero comando,
- \!:<n>*
: elenco dei parametri a partire dall'n-esimo
(compreso),
- \!:<n>-<m>
: elenco dei parametri a partire dall'n-esimo
(compreso) fino all'm-esimo(compreso),
- \!:<n>
: l'n-esimo argomento.
Ecco un esempio di utilizzo dei parametri con le funzioni (sh) e con l'alias (csh)
| Shell sh - File funzione.sh | Shell csh |
TestParametri ()
{
let i=1
echo "Nr. argomenti: $#"
echo "Elenco argomenti: $*"
for a
do
echo "$i Parametro: $a"
let i=i+1
done
}
TestParametri a b c d
|
[root@localhost ~]# alias TestParametri 'set s="\!*" ; set y=(\!*) ; \ echo Nr. argomenti: ${#y} ; \ echo "Elenco argomenti: $s" ; \ @ i = 1 ; \ foreach a ( $s ) \ echo "$i Parametro: $a" ; \ @ i++ ; \ end' [root@localhost ~]# TestParametri a b c Nr. argomenti: 3 Elenco argomenti: a b c 1 Parametro: a 2 Parametro: b 3 Parametro: c |
TRUCCHETTI/ESEMPI
SCRITTURA SU FILE:
Alla base di questo esempio abbiamo i simboli di ridirezione > e
>>. L'esempio, funzionante sia
in csh che sh, crea un file
Testo.txt
di 4 righe
echo Prima riga > TESTO.TXT echo Seconda riga >>TESTO.TXT echo Terza riga >>TESTO.TXT echo -- Creato il `date +%d/%m/%Y` alle `date +%H.%M.%S` >>TESTO.TXT echo Visualizza il FILE echo ------------------------ cat TESTO.TXT echo ------------------------ |
ATTESA:
Per sospendere l'esecuzione di uno script per un certo numero di secondi
possiamo usare in sh l'istruzione
read
| Shell sh - File wait.sh |
read -t3 -dX -s -p "Attendere 3 secondi (premi X per terminare) ..." ; echo |
In csh, per sospendere l'esecuzione di uno script per un certo numero di secondi, possiamo utilizzare la shell sh come se fosse un comando a cui passiamo, sotto forma di stringa (delimitata da '), la stessa istruzione di wait usata nell'esempio precedente.
| Shell csh - File wait.csh |
#!/bin/csh -f sh -c 'read -t3 -dX -s -p "Attendere 3 secondi (premi X per terminare) ... " ; echo' |
Si osservi che l'opzione
-c di
sh richiama la shell sh solo per eseguire
il comando passato come argomento e poi restituisce di nuovo il controllo alla csh
chiamante.
GENERAZIONE NUMERI CASUALI:
In sh la variabile $RANDOM può essere utilizzata per generare dei numeri casuali compresi da 0 a 32.767
(intero a 16 bit). L'esempio proposto genera un numero intero compreso
nell'intervallo[1,MAX_N]
| Shell sh - File RANDOM.sh |
let MAX_N=10 let N=$RANDOM let N=$(($N%$MAX_N))+1 echo N=$N |
In csh non esiste la variabile $RANDOM per cui utilizzo l'utility awk che fornisce una sorta di ambiente di programmazione (simile al C) orientato alla manipolazione delle stringhe
| Shell sh - File RANDOM.csh |
#!/bin/csh -f
@ MAX_N=10
@ N=`awk 'BEGIN {srand();x=sprintf("%d",rand()*100); print x}'`
@ N = $N % $MAX_N + 1
echo N=$N
|
FUNZIONE PER DETERMINARE IL GIORNO DI PASQUA PARTENDO DALL'ANNO
Vediamo ora un esempio di comando batch sh che utilizza una
funzione per determinare il giorno di pasqua partendo dall'anno:
| Shell sh - File GiorniPasquali.sh |
Pasqua ()
{
local a
let year=$1
Mesi=(Gennaio Febbraio Marzo Aprile Maggio Giugno
Luglio Agosto Settembre Ottobre Novembre Dicembre)
if [ $year -ge 1583 ]; then
# Calendario gregoriano
a=$((year % 19))
b=$((year / 100))
c=$((year % 100))
d=$((b / 4))
e=$((b % 4))
f=$(( (b + 8)/ 25))
g=$(( (b - f + 1) / 3))
h=$(( (19 * a + b - d - g + 15) % 30))
a=$((year % 19))
b=$((year / 100))
c=$((year % 100))
i=$(( c / 4))
k=$(( c % 4))
l=$(( (32 + 2 * e + 2 * i - h - k) % 7))
m=$(( (a + 11 * h + 22 * l) / 451))
n=$(( h + l - 7 * m + 114))
mese=${Mesi[$((n / 31 -1))]}
giorno=$(( n % 31 + 1))
else
# Calendario Giuliano
a=$((year % 4))
b=$((year % 7))
c=$((year % 19))
d=$(( (19 * c + 15) % 30))
e=$(((2 * a + 4 * b - d + 34) % 7))
f=$((d + e + 114))
mese=${Mesi[$((f / 31 - 1))]}
giorno=$((f % 31 + 1))
fi
echo "$giorno $mese $year"
}
# uso:
# ./GiorniPasquali.sh 2000 2010
for ((a=$1; a <= $2 ; a++))
do
Pasqua $a
done
echo;
|
GESTIONE DI UN MENU
l'output ottenuto è il seguente: si noti come il passare del tempo venga evidenziato con
l'aggiunta di * a fianco del titolo "ESEMPIO MENU".
CONTA=""
while :
do
clear
echo "---------------------------------------"
echo "ESEMPIO MENU $CONTA"
echo "---------------------------------------"
echo "1 - Menu A : Visualizza Ora"
echo "2 - Menu B : Visualizza Data"
echo "3 - Menu C : Azzera conteggio"
echo "4 - Exit"
echo "---------------------------------------"
echo;
opt=""
read -t2 -n1 -s -p "digita un'opzione: [1-4]: " opt
if [ -n $opt ]; then
echo;
fi
case "$opt" in
"" ) CONTA="$CONTA*";;
"1" ) echo "Ora corrente `date +%H.%M.%S`";
echo -n "Premi un tasto per continuare ...";
read -n1 enterKey;;
"2" ) echo "Data corrente: `date +%d/%m/%Y`";
echo -n "Premi un tasto per continuare ...";
read -n1 enterKey;;
"3" ) CONTA="";;
"4" ) echo "Bye Bye $USER";
break;;
* ) echo "$opt: opzione errata! Digita un numero tra 1 e 4";
echo -n "Premi un tasto per continuare ...";
read -n1 enterKey;;
esac
if [ "$CONTA" == "******" ]; then
CONTA=""
fi
done
---------------------------------------
ESEMPIO MENU ***
---------------------------------------
1 - Menu A : Visualizza Ora
2 - Menu B : Visualizza Data
3 - Menu C : Azzera conteggio
4 - Exit
---------------------------------------
digita un'opzione: [1-4]:
L'UTILITY AWK E LE ESPRESSIONI REGOLARI
L'utility
awk
(acronimo di Aho Weinberger Kerningan) richiede:
- un programma (nel linguaggio di awk),
- un'espressione regolare (pattern)
- un testo da esaminare
(che può arrivare anche tramite una pipe).
Il testo analizzato da
awk viene visto come
una sequenza di linee contenenti dei valori separati da opportuni separatori. Il
sorgente del programma in awk può essere digitato
direttamente sulla
linea di comando oppure scritto in un file esterno. Ogni istruzione di awk ha una sintassi di
questo tipo:
pattern
{comandi in linguaggio awk}
Vediamo ora
alcuni esempi:
a) Il primo esempio
awk '{print $3}' srcfile
stampa a video la terza
colonna del file
srcfile.
La separazione
in colonne/campi dei valori all'interno di una linea è determinato
dalla presenza di una qualsiasi combinazione di spazi o tab.
b) L’opzione -F permette di specificare un separatore per le colonne/campi diverso da quelli predefiniti (spazio e tabulazione). In questo esempio il comando awk (privo del pattern) utilizza come separatore i due punti :
d)
Nell'esempio successivo non è indicata alcuna azione da eseguire
(quella che è solitamente racchiusa tra {}).
In questo caso l'azione di default intrapresa è print $0 ovvero la
stampa, sullo standard output, delle linee che hanno soddisfatto i vincoli
imposti dal pattern. Il comando seguente:
awk '/^da_qui/,/^a_qui/' srcfile
stampa tutte le linee di srcfile
che risultano delimitate dalla linea che inizia con la sequenza
"da_qui" fino a quella che inizia per "a_qui".
e)
Un pattern può essere una espressione regolare
(molto usate con il comando grep)
o una condizione. Il comando
awk
converte automaticamente,
quando il contesto lo richiede, un campo in numero. Nell'esempio
successivo:
awk ‘$1 > 18{print $2}’ srcfile
verrà visualizzata la 2° colonna delle righe che hanno il primo campo maggiore
di 18.
Le espressioni regolari usano alcuni dei metacaratteri che
vengono utilizzati anche
dalla shell. Per questo motivo è necessario racchiuderle fra singolo apice.
f) Vediamo ora una serie di esempi. Tutti gli esempi analizzano il seguente file di testo (si noti la presenza di una linea vuota [contenente solo un invio]):
| File ELENCO |
m.1) Sechi Paolo f.2) Rosi Bruna m.3) Bianchi Pierpaolo m.4) Sechi Giulio^ m.5) Paolotto Mario* f.6) Bronchi Rosa- f.7) Fiini Marcella* m.8) Fabiana GianPaolo |
Analizziamo ora alcune regole nella costruzione delle espressioni regolari
- l'uso delle [] indica un elenco di alternative (ad esempio con [az] verifico
che contenga la lettera a oppure z)
- se all'interno delle [] la sequenza di lettere inizia per ^
allora viene verificata la negazione
(ad esempio con [^az] verifico che non contenga la lettera a
o z)
- se all'interno delle [] il carattere ^
non è all'inizio allora l'accento circonflesso ^ viene interpretato come
semplice carattere.
(ad esempio con [az^] verifico che contenga la lettera a oppure
z oppure ^)
- il carattere
^ all'inizio dell'espressione regolare indica che il controllo va fatto
all'inizio della linea (ad esempio ^[az] controlla che la linea inizi per
a o z)
- il . (punto) indica un qualsiasi carattere ad esclusione dell'invio (newline). Se
l'epressione regolare è composta dal solo . allora escludo dall'analisi le righe vuote
- il carattere $ in fondo all'espressione regolare indica che il controllo
va fatto alla fine della linea (ad esempio [az]$ verifica che la linea
finisca con a oppure z)
- il carattere * indica che il carattere che lo precede può apparire zero o
più volte
- il carattere + indica che il carattere che lo precede può apparire una o
più volte
- il carattere ? indica che il carattere che lo precede può apparire zero o una volta
- il carattere \ serve ad indicare che il carattere successivo non va interpretato come un
metacarattere
- la sequenza \< verifica la corrispondenza all’inizio di una parola
- la sequenza \> verifica la corrispondenza alla fine di una parola
- \<espressione_regolare\>" verifica la corrispondenza esatta su almeno una
delle parole contenute nella linea (la stringa "espressione_irregolare" non
verrà quindi riconosciuta)
- ^regolare$" verifica la corrispondenza esatta sul contenuto dell'intera linea
- un'espressione regolare, composta da "sottoespressioni regolari"
collegate
tra loro dalla |
(pipe), risulta verificata se almeno una delle sottoespressioni risulta verificata
(ad esempio: [iu|ie] estrae le righe che contengono la sottosequenza ie oppure
iu)
- Sequenze combinate di caratteri racchiusi tra parentesi quadre verificano le
possibili modalità di scrittura di una parola. Ad esempio "[Ss][Ii]"
controlla che si sia scritta una delle seguenti sequenze: si, SI, Si, sI. L'espressione regolare "[0-9][0-9][0-9][0-9][0-9]"
verifica la "compatibilità" di una stringa con le modalità di scrittura di
un codice di avviamento postale.
Ed ora ecco gli esempi:
|
|
|
g) Concludiamo con ulteriori esempi:
|
Esempio g.1)
Estraggo le linee che hanno il cognome che inizia per B e il
nome che termina per o oppure meno |
sh-2.05$ awk '( $2~/^B/ && $3~/[o-]$/ ) { print }' elenco m.3) Bianchi Pierpaolo f.6) Bronchi Rosa- sh-2.05$ awk '( $2~/^B/ && ($3~/o$/ || $3~/-$/ ) ) { print }' elenco m.3) Bianchi Pierpaolo f.6) Bronchi Rosa- |
Si osservi che la ~ (tilde) consente di verificare se se un campo "rispetta" l'espressione regolare scritta dopo la tilde. La sequenza !~ equivale a "non rispetta"
|
Esempio g.2)
Estraggo le linee che hanno il cognome che non inizia per
B e un
nome che termina per o oppure meno |
sh-2.05$ awk '( $2!~/^B/ && $3~/[o-]$/ ) { print }' elenco m.1) Sechi Paolo m.8) Fabiana GianPaolo sh-2.05$ awk '( $2!~/^B/ && ($3~/o$/ || $3~/-$/ ) ) { print }' elenco m.1) Sechi Paolo m.8) Fabiana GianPaolo |
| Esempio g.3) Estraggo le linee che hanno un cognome di almeno 8 lettere |
sh-2.05$ awk '( length($2)>=8 ) { print "Cognome: " $2 "\n" "Nome: " $3 }' elenco
Cognome: Paolotto
Nome: Mario*
|
E' possibile digitare
direttamente sia il testo da analizzare che lo script in
awk . Nel caso sia necessario scrivere il
programma awk su più linee basta inserire in fondo ad ogni linea il carattere \.
Quando ho,
nella stessa sezione (porzione di programma delimitato da {}),
più istruzioni le devo separare con ;.
Usando infine la funzione di ridirezione "here document" così
caratterizzata
<<marcatore
(tipicamente si usa come marcatore il nome EOF) posso
ridirigere verso lo standard input di un comando del testo digitato direttamente su più righe semplicemente scrivendolo tra due occorrenze di marcatore (l'ultima occorrenza deve apparire su una linea da sola).
|
Esempio g.4) Esempio di digitazione diretta sia
del testo da analizzare che dello script in awk distribuito su più linee |
sh-2.05$ awk 'BEGIN { f=0;m=0;n=0 } \ { n++;if (/^f./) { f++;print n"/"f " - (F) " $2 " " $3 } \ else if (/^m./) {m++ ; print n"/"m " - (M) " $3 " " $2 } } \ END {print "------ Fine" }' << EOF m.1) Sechi Paolo f.2) Rosi Bruna$ m.3) Bianchi Pierpaolo m.4) Sechi Giulio^ m.5) Paolotto Mario* f.6) Bronchi Rosa- f.7) Fiini Marcella* m.8) Fabiana GianPaolo EOF 1/1 - (M) Paolo Sechi 2/1 - (F) Rosi Bruna$ 3/2 - (M) Pierpaolo Bianchi 4/3 - (M) Giulio^ Sechi 6/4 - (M) Mario* Paolotto 7/2 - (F) Bronchi Rosa- 8/3 - (F) Fiini Marcella* 9/5 - (M) GianPaolo Fabiana ------ Fine |
Concludiamo con un lungo script in linguaggio awk. Il programma mostrato, per certi versi assurdo, ha come obbiettivo quello di illustrare l'uso dei vari costrutti, delle variabili predefinite e delle principali funzioni disponibili in awk
Nell'analisi dello script si tenga presente che in generale un prg awk è composto da queste sezioni
(tutte facoltative):
BEGIN {
istruzioni eseguite all'inizio prima della lettura del file
}
PATTERN1 {
istruzioni eseguite per ogni linea
che soddisfa il pattern1
}
PATTERN2 {
istruzioni eseguite per ogni linea che soddisfa il pattern2
}
...
{
istruzioni eseguite per ogni linea del file analizzata
}
END {
istruzioni eseguite al termine della lettura del file
}
| File Test.awk |
#!/bin/awk -f
# può essere eseguito con:
# ./test.awk <nomefile>
# oppure
# awk -f test.awk <nomefile>
# ------------------------------------------
# ELENCO FUNZIONI MATEMATICHE
# ------------------------------------------
# int(x) : Restituisce il valore intero (troncato ovvero int(1.7)=1) di x.
# sqrt(x) : Restituisce la radice quadrata di x.
# exp(x) : Restituisce la potenza di x.
# log(x) : Restituisce il logaritmo di x.
# sin(x) : Restituisce il seno di x, pero' x deve essere espresso in radianti.
# cos(x) : Restituisce il coseno di x, pero' x deve essere espresso in radianti.
# atan2(x/y) : Restituisce l'arco tngente di x/y, espresso in radianti.
# rand() : Da' un numero casuale tra zero e uno, ma mai zero.
# ------------------------------------------
# ELENCO FUNZIONI STRINGA
# ------------------------------------------
# index(frase, parola) : Restituisce la posizione del carattere dove comincia la parola
# nella frase data - il conteggio parte da 1 e se la parola non è presente
# dentro la frase restituisce 0
# match(frase, regexp) : match() somiglia abbastanza a index(), eccetto per il fatto che, invece
# di cercare una sottostringa, cerca una espressione regolare. La funzione
# match restituisce la posizione iniziale del match (corrispondenza), o zero
# se non c'è alcun match. Oltre a questo, match() cambia il valore di due
# variabili chiamate RSTART e RLENGTH. RSTART contiene il valore di ritorno
# (posizione del primo match) e RLENGTH specifica la sua lunghezza in caratteri
# (o -1 se nessun match è stato trovato). Usando RSTART, RLENGTH, substr() e un
# piccolo ciclo è possibile scorrere i vari match che compaiono nella vostra
# stringa.
# sub(regexp,newstr,str) : Sub() troverà la prima sequenza di caratteri in str che corrisponde all'espressione
# regolare regexp, e sostituirà la prima occorrenza di tale sequenza con la stringa
# newstr.
# gsub(regexp,newstr,str) : sub() e gsub() hanno gli stessi argomenti; l'unica cosa in cui sono diverse è
# che sub() sostituirà solo la prima corrispondenza di regexp (se esiste), e
# gsub() invece effettuerà una sostituzione globale, cambiando tutte le
# corrispondenze di regexp nella stringa.
# length(stringa) : Restituisce la lunghezza della stringa. Se non mettete nulla
# nelle parentesi vi restistuisce la lunghezza della stringa $0.
# toupper(stringa) : Converte la stringa in caratteri tutti maiuscoli.
# tolower(stringa) : Converte la stringa in caratteri tutti minuscoli.
# split(stringa, matrice, (separatore)) : Divide una stringa in pezzi delimitati dal separatore
# (se non indicato si intende lo spazio), e li mette nella matrice indicata
# come penultimo argomento.
# esempio: NrMesi=split("Gen,Feb,Mar,Apr,Mag,Giu,Lug,Ago,Set,Ott,Nov,Dic",Mesi,",")
# ------------------------------------------
# ELENCO FUNZIONI TEMPORALI
# ------------------------------------------
# systime() : Restituisce il tempo timestamp, cioe' in secondi passati
# dal 1/1/1970 alle 00:00:00 UTC.
# mktime("data") : Restituisce la data nel formato timestamp formato la data
# deve essere scritta nel seguente formato: YYYY MM DD HH mm SS.
# strftime((FORMATO),(TIMESTAMP)) :
# Senza TIMESTAMP restituisce la data attuale nel formato Sun Nov
# 14 13:44:57 CET 2004 se non è specificato il FORMATO altrimenti secondo
# lo stile indicato.
# Se viene indicato un timestamp verra' indicata, nel formato
# indicato, quella data. Il formato si specifica nel seguente modo:
#
# %a : Giorno della settimana abbreviato.
# %A : Giorno della settimana.
# %b : Mese dell'anno abbreviato.
# %B : Mese dell'anno.
# %c : Data nel formato predefinito.
# %C : Il secolo.
# %d : Il giorno del mese in formato numerico (01-31).
# %D : La data nel formato `%m/%d/%y.
# %e : Il giorno del mese in formato numerico ma con uno spazio al posto dello zero davanti ( 1-31).
# %F : La data in formato ISO-8601, cioe' %Y-%m-%d.
# %G : La settimana dell'anno secondo lo standard ISO.
# %h : E' uguale a %b.
# %H : L'ora nel formato 00-23.
# %I : L'ora nel formato 01-12.
# %j : Il giorno dell'anno (001-366).
# %m : Il mese in formato numerico.
# %M : I minuti (00-59).
# %n : A capo (carattere ASCII LF).
# %p : La scritta AM/PM riguardante l'ora.
# %r : L'ora in formato da 12, equivalente a %I:%M:%S %p.
# %R : L'ora equivalente a %H:%M.
# %S : I secondi.
# %t : Il carattere TAB.
# %T : L'ora nel formato %H:%M:%S.
# %u : Il giorno della settimana nel formato numerico (1-7) considerando lunedi' 1.
# %U : La settimana dell'anno considerando la domenica come primo giorno della settimana.(00-53)
# %V : La settimana dell'anno considerando il lunedi' come primo giorno della settimana.(01-53)
# %w : Il giorno della settimana in formato numerico, considerando la domenica come primo giorno della settimana.
# %W : La settimana dell'anno considerando il lunedi' come primo giorno della settimana.(00-53)
# %y : Le ultime due cifre dell'anno.
# %Y : L'anno con quattro cifre.
# %z : Il fuso orario nella forma +HHmm
# %Z : Il fuso orario con una sigla.
# %% Per ottenere il simolo percentuale %.
# ------------------------------------------
# ESEMPIO DI DICHIARAZIONE DI FUNZIONE
# ------------------------------------------
function print_sesso(sigla,progressivo)
{
if (sigla=="m")
printf("\tCampo 1: %d^ persona (maschio)\n",progressivo)
else
printf("\tCampo 1: %d^ persona (femmina)\n",progressivo)
}
# ----------------------------------
# Sezione eseguita all'inizio
# ----------------------------------
BEGIN {
# ------------------------------------------
# ESEMPIO USO VARIABILI AWK
# ------------------------------------------
print "----- INIZIO ----------------------------"
print "Delimitatore campo di input (FS) : " FS
print "Delimitatore campo di output (OFS) : " OFS
print "Delimitatore record di input (RS) : " RS
print "Delimitatore record di output (ORS) : " ORS
print "Formato di output dei numeri (OFMT): " OFMT
nrA=0
}
# Sezione eseguita per ogni riga che soddisfa il pattern /Sechi/
/Sechi/ { print "********* PATTERN /SECHI/ SODDISFATTO **********" }
# Sezione eseguita per ogni riga rielaborata
{
printf("-----%2d^ ITERAZIONE ------------------------\n",NR)
print "--> File(FILENAME) - Nr.Campi(NF): " FILENAME " - " NF
if ($0=="") next # proseguo con il ciclo successivo
# estraggo il nominativo
nrA++
nrCol=split($0,Arr,")") # split in un Array di una stringa
Nominativo[nrA]=Arr[nrCol]
# estraggo sesso ed il progressivo
posParentesi=length($1)
posPunto=index($1,".")
progressivo=int(substr($1,posPunto+1,posParentesi-posPunto-1))
sigla=substr($1,1,1)
print "Riga analizzata: " $0
print_sesso(sigla,progressivo)
for (i=2 ; i <= NF ; i++)
{
if (match($i,/Sechi/) > 0)
{
sub(/Sechi/,"*****",$i) # restituisce 0 se non sostituisce
printf("\tCampo %d: %s\n",i,$i)
}
else
printf("\tCampo %d: %s\n",i,toupper($i))
}
}
# Sezione eseguita alla fine
END {
print "----- FINE ------------------------------"
print "Nr righe nel file (FNR): " FNR
print "Nr righe analizzate: " nrA
NomiLetti=""
i=0
srand()
# esiste anche while (condizione=vera) { istruzioni }
do
{
i++
if (i % 2 ==0) continue # salto i pari
eta=int(rand()*30)+1 # numero casuale tra 1 e 30
# esempio di concatenazione di stringhe
NomiLetti=NomiLetti i ")" Nominativo[i] " - eta: " eta "\n"
} while (i < nrA)
# Potevo usare anche questa formula di for particolare.
# ATTENZIONE! L'elenco non risulta ordinato poichè dipende dalla gestione di awk
for (i in Nominativo)
{
if (i % 2 ==0) continue # salto i pari
eta=int(rand()*30)+1 # numero casuale tra 1 e 30
NomiLetti=NomiLetti i ")" Nominativo[i] " - eta: " eta "\n"
}
# elimino l'intero array
delete Nominativo
printf("%s",NomiLetti)
print strftime("%A, %e %B %Y%n%T",systime())
}
|
Che produce questo output
| Esempio 5) Esegue lo script test.awk |
sh-2.05$ awk -f test.awk elenco ----- INIZIO ---------------------------- Separatore campo di input (FS) : Separatore campo di output (OFS) : Separatore record di input (RS) : Separatore record di output (ORS) : Formato di output dei numeri(OFMT): %.6g ----- 1^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: m.1) Sechi Paolo Campo 1: 1^ persona (maschio) Campo 2: SECHI Campo 3: PAOLO ----- 2^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: f.2) Rosi Bruna$ Campo 1: 2^ persona (femmina) Campo 2: ROSI Campo 3: BRUNA$ ----- 3^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: m.3) Bianchi Pierpaolo Campo 1: 3^ persona (maschio) Campo 2: BIANCHI Campo 3: PIERPAOLO ----- 4^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: m.4) Sechi Giulio^ Campo 1: 4^ persona (maschio) Campo 2: SECHI Campo 3: GIULIO^ ----- 5^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 0 ----- 6^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: m.5) Paolotto Mario* Campo 1: 5^ persona (maschio) Campo 2: PAOLOTTO Campo 3: MARIO* ----- 7^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: f.6) Bronchi Rosa- Campo 1: 6^ persona (femmina) Campo 2: BRONCHI Campo 3: ROSA- ----- 8^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: f.7) Fiini Marcella* Campo 1: 7^ persona (femmina) Campo 2: FIINI Campo 3: MARCELLA* ----- 9^ ITERAZIONE ------------------------ --> File(FILENAME) - Nr.Campi(NF): elenco - 3 Riga analizzata: m.8) Fabiana GianPaolo Campo 1: 8^ persona (maschio) Campo 2: FABIANA Campo 3: GIANPAOLO ----- FINE ------------------------------ Nr righe nel file (FNR): 9 Nr righe analizzate: 8 1) Sechi Paolo - eta: 23 2) Rosi Bruna$ - eta: 23 3) Bianchi Pierpaolo - eta: 11 4) Sechi Giulio^ - eta: 2 5) Paolotto Mario* - eta: 15 6) Bronchi Rosa- - eta: 3 7) Fiini Marcella* - eta: 17 8) Fabiana GianPaolo - eta: 17 Wednesday, 28 April 2010 21:03:50 |
LINK - collegamenti
Elenchiamo qui alcuni link utili:
http://www.pluto.it/files/ildp/guide/abs/index.html (ITA)
http://dida.fauser.edu/info/cshell/cshell.htm (ITA)
http://www.freebsd.org/cgi/man.cgi (ENG)
http://www.grymoire.com/Unix/Sh.html (ENG)
http://www.grymoire.com/Unix/Csh.html (ENG)
http://www.grymoire.com/Unix/Awk.html (ENG)
http://tldp.org/LDP/abs/html/awk.html (ENG)
http://www.network-theory.co.uk/docs/bashref/index.html (ENG)
http://docstore.mik.ua/orelly/unix/ksh/index/idx_0.htm (ENG)
http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
(ENG)
http://tldp.org/LDP/Bash-Beginners-Guide/html/ (ENG)
http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
(ENG)
http://www.intuitive.com/wicked/table-of-contents.shtml (ENG)
http://www.staff.tugraz.at/reinfried.o.peter/unix/ (ENG)