Qual è il modo migliore per determinare se una variabile in bash è vuota ("")?
Ho sentito che si raccomanda di farlo if [ "x$variable" = "x" ]
È quello il modo corretto ? (ci deve essere qualcosa di più semplice)
Qual è il modo migliore per determinare se una variabile in bash è vuota ("")?
Ho sentito che si raccomanda di farlo if [ "x$variable" = "x" ]
È quello il modo corretto ? (ci deve essere qualcosa di più semplice)
Risposte:
Ciò restituirà true se una variabile non è impostata o è impostata sulla stringa vuota ("").
if [ -z "$VAR" ];
if [ ! -z "$VAR" ];
-z
è-n
if [ -n "$VAR" ];
$var
su una riga di comando verrà diviso per il suo spazio in un elenco di parametri, mentre "$var"
sarà sempre solo un parametro. Citando le variabili spesso è una buona pratica e ti impedisce di inciampare su nomi di file contenenti spazi bianchi (tra le altre cose). Esempio: dopo averlo fatto a="x --help"
, prova cat $a
- ti darà la pagina di aiuto per cat
. Quindi prova cat "$a"
- lo dirà (di solito) cat: x --help: No such file or directory
. In breve, cita presto e cita spesso e non te ne pentirai quasi mai.
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. È possibile semplificare il test per una variabile che fa contenere un valore di:
if [[ $variable ]]
Questa sintassi è compatibile con ksh (almeno ksh93, comunque). Non funziona con POSIX pure o con vecchie shell Bourne come sh o dash.
Vedi 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} ]]
if [[ $variable ]]
me ha funzionato bene e non ha nemmeno bisogno di set -u
quello richiesto da una delle altre soluzioni proposte.
sh
posto di Bash. Se hai bisogno delle maggiori capacità che offre, usa Bash e usalo completamente.
;
alla fine. Il then
può essere sulla riga successiva senza punto e virgola.
Una variabile in bash (e qualsiasi shell compatibile con POSIX) può trovarsi in uno dei tre stati:
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 ${VAR+foo}
costrutto si espande nella stringa vuota se VAR
non è impostato o foo
se VAR
è impostato su qualcosa (inclusa la stringa vuota).
Il ${VAR-foo}
costrutto si espande al valore di VAR
if impostato (incluso set su stringa vuota) e foo
se non impostato. Ciò è utile per fornire valori predefiniti sostituibili dall'utente (ad esempio, ${COLOR-red}
dice di usare a red
meno che la variabile non COLOR
sia stata impostata su qualcosa).
Il motivo per cui [ x"${VAR}" = x ]
è spesso consigliato per verificare se una variabile non è impostata o è impostata su una stringa vuota è perché alcune implementazioni del [
comando (note anche come test
) sono errate. Se VAR
è impostato su qualcosa di simile -n
, alcune implementazioni faranno la cosa sbagliata quando vengono fornite [ "${VAR}" = "" ]
perché il primo argomento a [
viene erroneamente interpretato come l' -n
operatore, non una stringa.
[ -z "${VAR-set}" ]
.
set -u
o set -o nounset
in bash, il test provocherà solo l'errore "bash: VAR: variabile non associata". Consultare stackoverflow.com/a/13864829 per un controllo unset più affidabile. Il mio go-to controlla se una variabile è nulla o non impostata [ -z "${VAR:-}" ]
. Il mio controllo per verificare se una variabile non è vuota è [ "${VAR:-}" ]
.
-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 $MY_PORT
variabile è vuota, allora PORT
viene impostato a 5432, altrimenti PORT viene impostato al valore di MY_PORT
. Nota che la sintassi include i due punti e il trattino.
set -o nounset
in alcuni script.
Un supplente che ho visto [ -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 non si accettano variabili non impostate (da set -u
o set -o nounset
), si verificheranno problemi con entrambi questi metodi. C'è una soluzione semplice a questo:
[ -z "${foo:-}" ]
Nota: questo lascerà la tua variabile indefinita.
-z
a pubs.opengroup.org/onlinepubs/009695399/utilities/test.html . Fondamentalmente, non è pensato per essere un'alternativa a -z
. Piuttosto, gestisce i casi in cui $foo
potrebbe espandersi a qualcosa che inizia con un metacarattere che [
o test
sarebbe stato confuso da. Mettere un non metacarattere arbitrario all'inizio elimina questa possibilità.
La domanda chiede come verificare se una variabile è una stringa vuota e per questo sono già state fornite le risposte migliori.
Ma sono arrivato qui dopo un periodo trascorso programmando in php e quello che stavo effettivamente cercando era un controllo come la funzione vuota in php che funziona 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 vuota 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 di php :
una variabile è considerata vuota se non esiste o se il suo valore è uno dei seguenti:
Naturalmente 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 che 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.
empty
: perché hai scritto [[ $( echo "1" ) ]] ; return
invece che semplicemente return 1
?
l'intero if-then e -z non sono necessari.
["$ foo"] && echo "foo non è vuoto" ["$ foo"] || echo "foo è davvero vuoto"
Questo è vero esattamente quando $ FOO è impostato e vuoto:
[ "${FOO+x}" = x ] && [ -z "$FOO" ]
Personalmente preferisco un modo più chiaro per verificare:
if [ "${VARIABLE}" == "" ]; then
echo VARIABLE is empty
else
echo VARIABLE is not empty
fi
estensione oneliner della soluzione di duffbeer703 :
#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
I miei 5 centesimi: c'è anche una sintassi più breve di if ...
, questa:
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 nella guida abs (cercare «Esempio 10-7»).
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).