7.3. Altri operatori di confronto

Un operatore di verifica binario confronta due variabili o due grandezze. da notare che i confronti fra interi utilizzano una serie di operatori diversa da quelli fra stringhe .

confronto di interi

-eq

uguale a

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

-ne

diverso (non uguale) da

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

-gt

maggiore di

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

-ge

maggiore di o uguale a

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

-lt

minore di

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

-le

minore di o uguale a

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

<

minore di (tra doppie parentesi)

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

<=

minore di o uguale a (tra doppie parentesi)

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

>

maggiore di (tra doppie parentesi)

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

>=

maggiore di o uguale a (tra doppie parentesi)

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

confronto di stringhe

=

uguale a

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

==

uguale a

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

sinonimo di =.

Nota

Il comportamento dell'operatore di confronto == all'interno del costrutto di verifica doppie parentesi quadre diverso rispetto a quello nel costrutto parentesi quadre singole.

[[ $a == z* ]]    # Vero se $a inizia con una "z" (corrispondenza di modello).
[[ $a == "z*" ]]  # Vero se $a  uguale a z* (corrispondenza letterale).

[ $a == z* ]      # Esegue il globbing e la divisione delle parole.
[ "$a" == "z*" ]  # Vero se $a  uguale a z* (corrispondenza letterale).

# Grazie a Stphane Chazelas

!=

diverso (non uguale) da

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

All'interno del costrutto [[ ... ]] questo operatore esegue la ricerca di corrispondenza.

<

inferiore a, in ordine alfabetico ASCII

if [[ "$a" < "$b" ]]

if [ "$a" \< "$b" ]

Si noti che "<" necessita dell'escaping nel costrutto [ ].

>

maggiore di, in ordine alfabetico ASCII

if [[ "$a" > "$b" ]]

if [ "$a" \> "$b" ]

Si noti che ">" necessita dell'escaping nel costrutto [ ].

Vedi Esempio 26-11 per un'applicazione di questo operatore di confronto.

-z

la stringa "nulla", cio, ha lunghezza zero

-n

la stringa non "nulla".

Attenzione

L'operatore -n richiede assolutamente il quoting della stringa all'interno delle parentesi quadre. L'utilizzo, tra le parentesi quadre, di una stringa senza quoting, sia con ! -z che da sola (vedi Esempio 7-6), normalmente funziona, tuttavia non una pratica sicura. Bisogna sempre utilizzare il quoting su una stringa da verificare. [1]

Esempio 7-5. Confronti numerici e di stringhe

#!/bin/bash

a=4
b=5

#  Qui "a" e "b" possono essere trattate sia come interi che come stringhe.
#  Ci si pu facilmente confondere tra i confronti numerici e quelli sulle 
#+ stringhe, perch le variabili Bash non sono tipizzate.
#
#  Bash consente le operazioni di interi e il confronto di variabili
#+ il cui valore  composto solamente da cifre.
#  Comunque attenzione, siete avvisati.

echo

if [ "$a" -ne "$b" ]
then
  echo "$a non  uguale a $b"
  echo "(confronto numerico)"
fi

echo

if [ "$a" != "$b" ]
then
  echo "$a non  uguale a $b."
  echo "(confronto di stringhe)"
  #     "4"  != "5"
  # ASCII 52 != ASCII 53
fi

# In questo particolare esempio funziona sia "-ne" che "!=".

echo

exit 0

Esempio 7-6. Verificare se una stringa nulla

#!/bin/bash
# str-test.sh: Verifica di stringhe nulle e di stringhe senza quoting (*)

# Utilizzando   if [ ... ]


# Se una stringa non  stata inizializzata, non ha un valore definito.
# Questo stato si dice "nullo" (non zero!).

if [ -n $stringa1 ]    # $stringa1 non  stata dichiarata o inizializzata.
then
  echo "La stringa \"stringa1\" non  nulla."
else  
  echo "La stringa \"stringa1\"  nulla."
fi  

# Risultato sbagliato.
# Viene visualizzato $stringa1 come non nulla, anche se non era inizializzata.

echo


# Proviamo ancora.

if [ -n "$stringa1" ]  # Questa volta  stato applicato il quoting a $stringa1.
then
  echo "la stringa \"stringa1\" non  nulla."
else  
  echo "La stringa \"stringa1\"  nulla."
fi                     #  Usate il quoting per le stringhe nel costrutto
                       #+ di verifica parentesi quadre!


echo


if [ $stringa1 ]       # Qui, $stringa1  sola.
then
  echo "La stringa \"stringa1\" non  nulla."
else  
  echo "La stringa \"stringa1\"  nulla."
fi  

#  Questo funziona bene.
#  L'operatore di verifica [ ] da solo  in grado di rilevare se la stringa
#+  nulla.
#  Tuttavia  buona pratica usare il quoting ("$stringa1").
#
# Come ha evidenziato Stephane Chazelas,
#    if [ $stringa1 ]    ha un argomento, "]"
#    if [ "$stringa1" ]  ha due argomenti, la stringa vuota "$stringa1" e "]"


echo



stringa1=inizializzata

if [ $stringa1 ]       # Ancora, $stringa1 da sola.
then
  echo "La stringa \"stringa1\" non  nulla."
else  
  echo "La stringa \"stringa1\"  nulla."
fi  

# Ancora, risultato corretto.
# Nondimeno,  meglio utilizzare il quoting ("$stringa1"), perch. . .

stringa1="a = b"

if [ $stringa1 ]       # Ancora $stringa1 da sola.
then
  echo "La stringa \"stringa1\" non  nulla."
else  
  echo "La stringa \"stringa1\"  nulla."
fi  

# Senza il quoting di "$stringa1" ora si ottiene un risultato sbagliato!

exit 0

# Grazie anche a Florian Wisser per la "citazione iniziale".

# (*) L'intestazione di commento originaria recita "Testing null strings
#+ and unquoted strings, but not strings and sealing wax, not to
# mention cabbages and kings ..." attribuita a Florian Wisser. La
# seconda riga non  stata tradotta in quanto, la sua traduzione
# letterale, non avrebbe avuto alcun senso nel contesto attuale
# (N.d.T.).  

Esempio 7-7. zmore

#!/bin/bash
#zmore

# Visualizza i file gzip con  'more'

NOARG=65
NONTROVATO=66
NONGZIP=67

if [ $# -eq 0 ] # stesso risultato di:  if [ -z "$1" ]
# $1 pu esserci, ma essere vuota:  zmore "" arg2 arg3
then
  echo "Utilizzo: `basename $0` nomefile" >&2
  # Messaggio d'errore allo stderr.
  exit $NOARG
  # Restituisce 65 come exit status dello script (codice d'errore).
fi  

nomefile=$1

if [ ! -f "$nomefile" ]   # Il quoting di $nomefile mantiene gli spazi.
then
  echo "File $nomefile non trovato!" >&2
  # Messaggio d'errore allo stderr.
  exit $NONTROVATO
fi  

if [ ${nomefile##*.} != "gz" ]
# Uso delle parentesi graffe nella sostituzione di variabile.
then
  echo "Il file $1 non  un file gzip!"
  exit $NONGZIP
fi  

zcat $1 | more

# Usa il filtro 'more.'
# Lo si pu sostituire con 'less', se si desidera.


exit $?   # Lo script restituisce l'exit status della pipe.
# In questo punto dello script  "exit $?"  inutile perch lo script, 
# in ogni caso, restituir l'exit status dell'ultimo comando eseguito.

confronti composti

-a

and logico

exp1 -a exp2 restituisce vero se entrambe exp1 e exp2 sono vere.

-o

or logico

exp1 -o exp2 restituisce vero se vera o exp1 o exp2.

Sono simili agli operatori di confronto Bash && e || utilizzati all'interno delle doppie parentesi quadre.

[[ condizione1 && condizione2 ]]
Gli operatori -o e -a vengono utilizzati con il comando test o all'interno delle parentesi quadre singole.
if [ "$exp1" -a "$exp2" ]

Fate riferimento ad Esempio 8-3, Esempio 26-16 e Esempio A-29 per vedere all'opera gli operatori di confronto composto.

Note

[1]

Come sottolinea S.C., in una verifica composta, il quoting di una variabile stringa pu non essere sufficiente. [ -n "$stringa" -o "$a" = "$b" ] potrebbe, con alcune versioni di Bash, provocare un errore se $stringa fosse vuota. Il modo per evitarlo quello di aggiungere un carattere extra alle variabili che potrebbero essere vuote, [ "x$stringa" != x -o "x$a" = "x$b" ] (le "x" si annullano).