Come posso verificare se una variabile è vuota o contiene solo spazi?

La seguente sintassi bash verifica se param non è “t vuoto:

 [[ ! -z $param ]] 

Ad esempio:

param="" [[ ! -z $param ]] && echo "I am not zero" 

Nessun output e va bene.

Ma quando param è vuoto ad eccezione di uno (o più) caratteri di spazio, quindi il caso è diverso:

param=" " # one space [[ ! -z $param ]] && echo "I am not zero" 

“Non lo sono zero “viene visualizzato.

Come posso modificare il test per considerare le variabili che contengono solo caratteri spazio come vuote?

Commenti

  • Da man test: -z STRING - the length of STRING is zero. Se desideri rimuovere tutti gli spazi in $param, utilizza ${param// /}
  • WOW non esiste una semplice funzione trim() incorporata per qualche * nix? Tanti hack diversi per ottenere qualcosa di così semplice …
  • @ADTC $ (sed ‘ s / ^ \ s + | \ s + $ // g ‘ < < < $ string) mi sembra abbastanza semplice. Perché reinventare la ruota?
  • Perché potrebbe essere più brillante
  • Basta notare che [[ ! -z $param ]] è equivalente a test ! -z $param.

Risposta

Innanzitutto, tieni presente che -z test è esplicitamente per:

la lunghezza della stringa è zero

Ovvero, una stringa contenente solo spazi deve non essere vero in -z, perché ha una lunghezza diversa da zero.

Quello che vuoi è rimuovere gli spazi dalla variabile utilizzando espansione del parametro di sostituzione del pattern :

[[ -z "${param// }" ]] 

Questo espande param variabile e sostituisce tutte le corrispondenze del modello (un singolo spazio) con niente, quindi una stringa che contiene solo spazi verrà espansa in un stringa vuota.


La nitidezza di come funziona è che ${var/pattern/string} sostituisce la prima corrispondenza più lunga di pattern con string. Quando pattern inizia con / (come sopra), sostituisce tutte le corrispondenze. Poiché la sostituzione è vuota, possiamo omettere il / e il valore string:

$ {parametro / pattern / string}

Il pattern viene espanso per produrre un pattern proprio come nellespansione del nome del file. Il parametro viene espanso e la corrispondenza più lunga di pattern rispetto al suo valore viene sostituita con stringa . Se pattern inizia con “/”, tutte le corrispondenze di pattern vengono sostituite con stringa . Normalmente viene sostituita solo la prima corrispondenza. … Se la stringa è nulla, le corrispondenze di modello vengono eliminate e il / seguente modello può essere omesso.

Dopo tutto ciò, ci ritroviamo con ${param// } per eliminare tutti gli spazi.

Nota che però presente in ksh (dove ha avuto origine), zsh e bash, tale sintassi non è POSIX e non deve essere utilizzato negli sh script.

Commenti

  • use sed hanno detto … solo echo la variabile che hanno detto …
  • Hmm. Se è ${var/pattern/string}, ‘ deve essere [[ -z ${param/ /} ]] con lo spazio tra le barre essere lo schema e niente dopo essere la stringa?
  • @JesseChisholm ” Poiché la sostituzione è vuota, possiamo omettere la / finale e il valore della stringa “; ” Se stringa è nulla, le corrispondenze di modello vengono eliminate e il modello / seguente potrebbe essere omesso. ”
  • @MichaelHomer La risposta [[ -z "${param// }" ]] sembra essere pattern è vuoto e replacement string è un singolo spazio. AH! Lo vedo ora if pattern begins with a slash Mi sono perso quella parte. quindi lo schema è / e la stringa viene lasciata e quindi vuota. Grazie.
  • nota di bash: se è in esecuzione in set -o nounset (set -u) e param non è impostato (anziché null o riempito di spazio), allora questo genererà un errore di variabile non associata. (set + u; …..) esenterebbe questo test.

Rispondi

Il modo più semplice verificare che una stringa contenga solo caratteri in un set autorizzato significa verificare la presenza di caratteri non autorizzati.Pertanto, invece di verificare se la stringa contiene solo spazi, verifica se la stringa contiene un carattere diverso dallo spazio. In bash, ksh o zsh:

if [[ $param = *[!\ ]* ]]; then echo "\$param contains characters other than space" else echo "\$param consists of spaces only" fi 

“Consiste solo di spazi” include il caso di una variabile vuota (o non impostata).

Potresti voler testare qualsiasi carattere di spazio bianco. Utilizza [[ $param = *[^[:space:]]* ]] per utilizzare le impostazioni locali o qualsiasi elenco esplicito di caratteri di spazio vuoto che desideri verificare, ad es. [[ $param = *[$" \t\n"]* ]] per verificare la presenza di spazio, tabulazione o nuova riga.

Corrispondenza di una stringa con un modello con = allinterno di [[ … ]] è unestensione ksh (presente anche in bash e zsh). In qualsiasi stile Bourne / POSIX, puoi utilizzare il costrutto case per confrontare una stringa con un modello. Tieni presente che i modelli di shell standard utilizzano ! per negare un set di caratteri, anziché ^ come nella maggior parte delle sintassi delle espressioni regolari.

case "$param" in *[!\ ]*) echo "\$param contains characters other than space";; *) echo "\$param consists of spaces only";; esac 

Per verificare la presenza di spazi vuoti, la sintassi $"…" è specifica di ksh / bash / zsh; puoi inserire questi caratteri nel tuo script letteralmente (nota che una nuova riga dovrà essere racchiusa tra virgolette, poiché la barra rovesciata + la nuova riga non si espande fino a diventare nulla) o generarli, ad es.

whitespace=$(printf "\n\t ") case "$param" in *[!$whitespace]*) echo "\$param contains non-whitespace characters";; *) echo "\$param consists of whitespace only";; esac 

Commenti

  • Questo è quasi eccellente – ma, per ora, non risponde alla domanda come posta. Attualmente può dirti la differenza tra una variabile di shell vuota o non impostata e una che contiene solo spazi. Se accetti il mio suggerimento, aggiungerai il modulo di espansione dei parametri non ancora convergente da qualsiasi altra risposta che verifica esplicitamente che una variabile di shell sia impostata – intendo ${var?not set} – superando quel test e sopravvivendo assicurerebbe che una variabile corrispondente al tuo *) case effettui una risposta definitiva, ad esempio.
  • Correzione – questo, infatti, risponderebbe alla domanda originariamente posta, ma da allora è stata modificata in modo tale da cambiare radicalmente il significato della domanda e quindi invalidare la tua risposta.
  • È necessario [[ $param = *[!\ ]* ]] in mksh.

Risposta

POSSIBILMENTE:

case $var in (*[![:blank:]]*) echo "$var contains non blank";; (*) echo "$var contains only blanks or is empty or unset" esac 

Per distinguere tra vuoto e non vuoto , vuoto , non impostato :

case ${var+x$var} in (x) echo empty;; ("") echo unset;; (x*[![:blank:]]*) echo non-blank;; (*) echo blank esac 

[:blank:] è per i caratteri di spaziatura orizzontale (spazio e tabulazione in A SCII, ma probabilmente ce ne sono altri nel tuo locale; alcuni sistemi includeranno lo spazio unificatore (dove disponibile), altri non lo faranno). Se desideri anche caratteri di spaziatura verticale (come newline o form-feed), sostituisci [:blank:] con [:space:].

Commenti

  • POSIXly è lideale perché funzionerà con il (probabilmente migliore) trattino.
  • zsh sembra avere problemi con [![:blank:]], solleva :b è un modificatore non valido. In sh e ksh emula, genera un evento non trovato per [
  • @cuonglm, cosa hai provato? var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac' va bene per me. Levento non trovato riguarderebbe solo le shell interattive.
  • @St é phaneChazelas: Ah, giusto, ho provato con le shell interattive. Il :b modificatore non valido è un po strano.
  • @FranklinYu, su OS / X sh è costruito con --enable-xpg-echo-default e --enable-strict-posix-default in modo da essere conforme a Unix (che implica echo '\t' output di una tabulazione).

Risposta

Lunico motivo rimanente per scrivere uno script di shell, invece di uno script in un buon linguaggio di scripting, è se la portabilità estrema è una preoccupazione prioritaria. Leredità /bin/sh è lunica cosa che puoi essere certo di avere, ma Perl, ad esempio, è più probabilmente disponibile multipiattaforma rispetto a Bash. Pertanto, non scrivere mai script di shell che utilizzano funzionalità che non sono “t veramente universali ” e tieni presente che diversi fornitori Unix proprietari hanno congelato il loro ambiente di shell prima di POSIX.1-2001 .

Esiste un modo portatile per eseguire questo test, ma devi utilizzare tr:

[ "x`printf "%s" "$var" | tr -d "$IFS"`" = x ] 

(Il valore predefinito di $IFS, convenientemente, è uno spazio, una tabulazione e una nuova riga.)

(Il printf incorporato è di per sé molto portatile, ma affidarsi ad esso è molto meno complicato che capire quale variante di echo possiedi.)

Commenti

  • Questo ‘ è un po complicato.Il solito modo portatile per verificare se una stringa contiene determinati caratteri è con case .
  • @Gilles I don ‘ non credo che ‘ sia possibile scrivere un case glob in rileva una stringa che è vuota o contiene solo caratteri di spazio. (Sarebbe facile con unespressione regolare, ma case ‘ non esegue espressioni regolari. Il costrutto nella tua risposta ha vinto ‘ t funziona se ti interessano i newline.)
  • Ho fornito spazi come esempio nella mia risposta perché ‘ è la domanda ha chiesto per. ‘ è altrettanto facile testare i caratteri di spazio: case $param in *[![:space:]]*) …. Se vuoi testare i caratteri IFS, puoi utilizzare il pattern *[$IFS]*.
  • @mikeserv In un vero Script difensivo seriamente , imposti esplicitamente IFS su <space><tab><newline> allinizio e poi non lo tocchi mai più. Ho pensato che ‘ potesse essere una distrazione.
  • Per quanto riguarda le variabili nei pattern, penso che funzioni in tutte le versioni Bourne e in tutte le shell POSIX; richiederebbe codice aggiuntivo per rilevare modelli di maiuscole e minuscole e disattivare lespansione delle variabili e non posso ‘ trovare una ragione per farlo. Ne ho un paio di istanze nel mio .profile che è stato eseguito da molte shell Bourne. Ovviamente [$IFS] ha vinto ‘ non ha fatto ciò che era previsto se IFS ha determinati valori non predefiniti valori (vuoto (o non impostato), contenente ], che inizia con ! o ^) .

Risposta

if [[ -n "${variable_name/[ ]*\n/}" ]] then #execute if the the variable is not empty and contains non space characters else #execute if the variable is empty or contains only spaces fi 

Commenti

  • questo elimina qualsiasi carattere di spazio bianco, non solo un singolo spazio, giusto? grazie

Risposta

Per verificare se la variabile è vuota o contiene spazi, puoi anche utilizzare questo codice:

${name:?variable is empty} 

Commenti

  • Penso che la tua risposta sia sottovalutata perché ” o contenere spazi ” non è vero.
  • fai attenzione: questo uccide la shell corrente. Meglio metterlo in una (: $ {subshell?}). Inoltre, questo scriverà su stderr, probabilmente vorrai il reindirizzamento. E più importante che restituisce il valore effettivo della variabile ‘ se non è annullato o nullo. Se ‘ è presente un comando, lo hai appena eseguito. ‘ è meglio eseguire quel test su :.
  • come ucciderà la shell. e puoi anche testarlo, prima definisci name=aaaa quindi esegui questo comando echo ${name:?variable is empty} stamperà il valore del nome della variabile e ora esegui questo comando echo ${name1:?variable is empty} stamperà -sh: name1: la variabile è vuota
  • Sì – echo ${name:?variable is empty} valuterà $name ‘ un valore non nullo oppure ucciderà la shell. Quindi, per lo stesso motivo per cui non ‘ prompt > $randomvar non dovresti nemmeno ${var?} – se cè ‘ un comando lì dentro, ‘ probabilmente verrà eseguito e tu non ‘ t so cosè. Una shell interattiva non ‘ deve uscire, motivo per cui la tua non ‘ t. Tuttavia, se vuoi vedere alcuni test, ce ne sono molti qui . Questo non è ‘ abbastanza lungo …

Risposta

Il codice che hai pubblicato [[ ! -z $param ]] && echo "I am not zero" stamperà I am not zero se param è o unset / undefined o vuoto (in bash, ksh e zsh).

Per anche stampa se param contiene solo spazi (rimuovi spazi), POSIXly (per una gamma più ampia di shell):

 [ -z "${param#"${param%%[! ]*}"}" ] && echo "empty" 

Spiegazione:

  • Un ${param# … } rimuove un testo.
  • Il testo iniziale è dato da: ${param%%[! ]*}
  • che si espande in tutti gli spazi prima di qualsiasi non spazio carattere, ovvero tutti gli spazi iniziali.

Il risultato finale dellintera espansione è che tutti gli spazi iniziali vengono rimossi.

Questo risultato espanso viene verificato se di lunghezza 0.

  • Se il risultato è vuoto, la variabile era vuota oppure
  • rimuove gli spazi iniziali lha resa vuota.

Pertanto, se il test è vero, la variabile era già vuota o conteneva solo spazi al suo interno.


Il concetto è facile da estendere a più tipi di carattere. Per includere anche le tabulazioni, inserisci una tabulazione esplicita allinterno dellespressione tra parentesi:

 [ -z "${param#"${param%%[! ]*}"}" ] && echo "empty" 

o utilizza una variabile con i caratteri che devi rimuovere:

 var=$" \t" # in ksh, bash, zsh [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty" 

oppure puoi utilizzare qualche “espressione di classe di caratteri” POSIX (vuoto significa spazio e tabulazione):

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty" 

Risposta

Per controllare se la variabile ha solo spazi, incluso in una variabile a più righe , prova questo:

[[ $var = *[$" \t\n"]* ]] 

O con xargs:

[[ -z $(echo $var | xargs) ]] 

Oppure con sed:

[[ -z $(sed "/^$/d" <<< $var) ]] 

Answer

Prova questo:

$ [[ -z \`echo $n\` ]] && echo zero zero 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *