it-swarm.it

Come determinare se una variabile bash è vuota?

Qual è il modo migliore per determinare se una variabile in bash è vuota ("")?

Ho sentito che si consiglia di fare if [ "x$variable" = "x" ]

È il modo corretto? (ci deve essere qualcosa di più semplice)

784
Brent

Ciò restituirà true se una variabile non è impostata o è impostata sulla stringa vuota ("").

if [ -z "$VAR" ];
1075
duffbeer703

In Bash, quando non sei interessato alla portabilità verso shell che non la supportano, dovresti sempre usare la sintassi a doppia parentesi:

Uno dei seguenti:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

In Bash, usando parentesi quadre doppie, le virgolette non sono necessarie. Puoi semplificare il test per una variabile che contiene contiene un valore per:

if [[ $variable ]]

Questa sintassi è compatibile con ksh (almeno ksh93, comunque). Non funziona con POSIX pure o con vecchie shell Bourne come sh o dash.

Vedere la mia risposta qui e BashFAQ/031 per ulteriori informazioni sulle differenze tra parentesi quadre doppie e singole.

Puoi verificare se una variabile non è specificatamente impostata (come distinta da una stringa vuota):

if [[ -z ${variable+x} ]]

dove la "x" è arbitraria.

Se vuoi sapere se una variabile è nulla ma non è impostata:

if [[ -z $variable && ${variable+x} ]]

Una variabile in bash (e qualsiasi shell compatibile con POSIX) può trovarsi in uno dei tre stati:

  • non settato
  • impostato sulla stringa vuota
  • impostato su una stringa non vuota

Il più delle volte devi solo sapere se una variabile è impostata su una stringa non vuota, ma a volte è importante distinguere tra non impostato e impostato su una stringa vuota.

I seguenti sono esempi di come è possibile testare le varie possibilità e funziona con bash o con qualsiasi shell compatibile con POSIX:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

Ecco la stessa cosa ma in una comoda tabella:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

Il costrutto ${VAR+foo} Si espande nella stringa vuota se VAR non è impostato o in foo se VAR è impostato su qualcosa (inclusa la stringa vuota).

Il costrutto ${VAR-foo} Si espande al valore di VAR se impostato (incluso impostato su stringa vuota) e foo se non impostato. Ciò è utile per fornire valori predefiniti sostituibili dall'utente (ad esempio, ${COLOR-red} Dice di usare red a meno che la variabile COLOR sia stata impostata su qualcosa).

Il motivo per cui [ x"${VAR}" = x ] È spesso raccomandato per verificare se una variabile non è impostata o è impostata su una stringa vuota è perché alcune implementazioni del comando [ (Noto anche come test) sono buggy. Se VAR è impostato su qualcosa come -n, Alcune implementazioni faranno la cosa sbagliata quando viene dato [ "${VAR}" = "" ] Perché il primo argomento di [ Viene erroneamente interpretato come l'operatore -n, non una stringa.

239
Richard Hansen

-z È il modo migliore.

Un'altra opzione che ho usato è impostare una variabile, ma può essere sostituita da un'altra variabile, ad es

export PORT=${MY_PORT:-5432}

Se la variabile $MY_PORT È vuota, allora PORT viene impostato su 5432, altrimenti PORT viene impostato sul valore di MY_PORT. Nota che la sintassi include i due punti e il trattino.

38
Rory

Se sei interessato a distinguere i casi di set-empty rispetto a unset set, guarda l'opzione -u per bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true
24
MikeyB

Un supplente che ho visto a [ -z "$foo" ] è il seguente, tuttavia non sono sicuro del motivo per cui le persone usano questo metodo, qualcuno lo sa?

[ "x${foo}" = "x" ]

Ad ogni modo, se stai vietando le variabili non impostate (o da set -u o set -o nounset), allora avrai dei problemi con entrambi questi metodi. C'è una soluzione semplice a questo:

[ -z "${foo:-}" ]

Nota: questo lascerà la tua variabile indefinita.

8
errant.info

La domanda chiede come verificare se una variabile è una stringa vuota e le migliori risposte sono già state fornite per questo.
Ma sono atterrato qui dopo un periodo di programmazione in php e quello che stavo effettivamente cercando era un assegno come la funzione svuota in php lavorando in una shell bash.
Dopo aver letto le risposte mi sono reso conto che non stavo pensando correttamente in bash, ma comunque in quel momento una funzione come vuoto in php sarebbe stata davvero utile nel mio codice bash.
Dato che penso che ciò possa accadere ad altri, ho deciso di convertire la funzione php empty in bash

Secondo il manuale php :
una variabile è considerata vuota se non esiste o se il suo valore è uno dei seguenti:

  • "" (una stringa vuota)
  • 0 (0 as an integer)
  • 0.0 (0 come float)
  • "0" (0 come stringa)
  • un array vuoto
  • una variabile dichiarata, ma senza un valore

Ovviamente i casi null e false non possono essere convertiti in bash, quindi vengono omessi.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    Elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    Elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Esempio di utilizzo:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Demo:
il seguente frammento:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

uscite:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

Detto questo, in una logica bash i controlli su zero in questa funzione possono causare problemi collaterali, chiunque usi questa funzione dovrebbe valutare questo rischio e forse decidere di tagliare quei controlli lasciando solo il primo .

6
Luca Borrione

I miei 5 centesimi: c'è anche una sintassi più breve di if ..., questo:

VALUE="${1?"Usage: $0 value"}"

Questa riga imposterà VALUE se è stato fornito un argomento e stamperà un messaggio di errore anteposto al numero della riga dello script in caso di errore (e terminerà l'esecuzione dello script).

Un altro esempio può essere trovato in abs-guide (cerca "Esempio 10-7").

5
gluk47

l'intero if-then e -z non sono necessari.

 ["$ foo"] && echo "foo non è vuoto" 
 ["$ foo"] || echo "foo is effettivamente vuoto" 
5
namewithoutwords

Questo è vero esattamente quando $ FOO è impostato e vuoto:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]
4
JHS

estensione oneliner della soluzione duffbeer7 :

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
4
andrej

Personalmente preferisco un modo più chiaro per verificare:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi
4
Fedir RYKHTIK

Non è una risposta esatta, ma ho incontrato questo trucco. Se la stringa che stai cercando proviene da "un comando", puoi effettivamente memorizzare il comando in un env. e quindi eseguirlo ogni volta per l'istruzione if, quindi non sono necessarie parentesi!

Ad esempio questo comando, che determina se sei su debian:

grep debian /proc/version

esempio completo:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

Quindi questo è come un modo indiretto (rieseguendolo ogni volta) per verificare la presenza di una stringa vuota (sembra che stia verificando la risposta di errore dal comando, ma capita anche di restituire una stringa vuota).

0
rogerdpack