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 Stéphane 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).