Următoarea sintaxă bash verifică dacă param
nu este „gol:
[[ ! -z $param ]]
De exemplu:
param="" [[ ! -z $param ]] && echo "I am not zero"
Fără ieșire și bine.
Dar când param
este gol, cu excepția unuia (sau mai multor) caractere spațiale, atunci cazul este diferit:
param=" " # one space [[ ! -z $param ]] && echo "I am not zero"
„Eu nu sunt zero „este afișat.
Cum pot modifica testul pentru a considera variabilele care conțin doar caractere spațiale ca fiind goale?
Comentarii
- Din
man test
:-z STRING - the length of STRING is zero
. Dacă doriți să eliminați toate spațiile din$param
, utilizați${param// /}
- WOW nu există o funcție simplă
trim()
încorporată în vreo * nix? Atât de multe hack-uri diferite pentru a realiza ceva atât de simplu … - @ADTC $ (sed ‘ s / ^ \ s + | \ s + $ // g ‘ < < < $ string) mi se pare suficient de simplu. De ce să reinventăm roata?
- Pentru că ar putea fi mai strălucitoare
- Doar menționând că
[[ ! -z $param ]]
este echivalent cutest ! -z $param
.
Răspuns
Mai întâi, rețineți că -z
test este explicit pentru:
lungimea șirului este zero
Adică, un șir care conține numai spații ar trebui nu fi adevărat sub -z
, deoarece are o lungime diferită de zero.
Ce doriți este să eliminați spațiile din variabilă utilizând extinderea parametrului de înlocuire a modelului :
[[ -z "${param// }" ]]
Aceasta extinde param
variabilă și înlocuiește toate meciurile modelului (un singur spațiu) cu nimic, astfel încât un șir care are numai spații în el va fi extins la șir gol.
nitty-gritty a modului în care funcționează este ${var/pattern/string}
înlocuiește primul cel mai lung meci din pattern
cu string
. Când pattern
începe cu /
(ca mai sus), atunci înlocuiește toate potrivirile. Deoarece înlocuirea este goală, putem omite /
final și valoarea string
:
$ {parametru / model / șir}
șablonul este extins pentru a produce un șablon la fel ca în expansiunea numelui de fișier. Parametrul este extins și cea mai lungă potrivire a modelului cu valoarea acestuia este înlocuită cu șir . Dacă model începe cu ‘/’, toate potrivirile din model sunt înlocuite cu șir . În mod normal, doar primul meci este înlocuit. … Dacă șir este nul, potrivirile din șablon sunt șterse și rmătorul șablon poate fi omis.
După toate acestea, ajungem cu ${param// }
pentru a șterge toate spațiile.
Rețineți că, deși prezent în ksh
(de unde a provenit), zsh
și bash
, sintaxa respectivă nu este POSIX și nu trebuie utilizat în scripturile sh
.
Comentarii
Răspuns
Modul ușor a verifica dacă un șir conține doar caractere într-un set autorizat înseamnă a testa prezența caracterelor neautorizate.Astfel, în loc să testați dacă șirul conține doar spații, testați dacă șirul conține alt caracter decât spațiul. În bash, ksh sau zsh:
if [[ $param = *[!\ ]* ]]; then echo "\$param contains characters other than space" else echo "\$param consists of spaces only" fi
„Constă doar din spații” include cazul unei variabile goale (sau nesetate).
Poate doriți să testați orice caracter spațial. Utilizați [[ $param = *[^[:space:]]* ]]
pentru a utiliza setările locale sau orice altă listă explicită de caractere spațiale pe care doriți să le testați, de ex. [[ $param = *[$" \t\n"]* ]]
pentru a testa spațiul, fila sau linia nouă.
Potrivirea unui șir cu un model cu =
în interiorul [[ … ]]
este o extensie ksh (prezentă și în bash și zsh). În orice stil Bourne / POSIX, puteți utiliza construcția case
pentru a potrivi un șir cu un model. Rețineți că modelele standard ale shell-ului folosesc !
pentru a anula un set de caractere, mai degrabă decât ^
ca în majoritatea sintaxelor expresiilor regulate.
case "$param" in *[!\ ]*) echo "\$param contains characters other than space";; *) echo "\$param consists of spaces only";; esac
Pentru a testa caracterele spațiului alb, sintaxa $"…"
este specifică ksh / bash / zsh; puteți introduce aceste caractere în scriptul dvs. literalmente (rețineți că o linie nouă va trebui să fie cuprinsă între ghilimele, deoarece backslash + newline nu se extinde la nimic), sau să le generați, de exemplu
whitespace=$(printf "\n\t ") case "$param" in *[!$whitespace]*) echo "\$param contains non-whitespace characters";; *) echo "\$param consists of whitespace only";; esac
Comentarii
- Acesta este aproape excelent – dar, deocamdată, nu răspunde la întrebarea așa cum a fost pusă. În prezent, vă poate spune diferența dintre o variabilă shell sau goală necompletată și una care conține doar spații. Dacă veți accepta sugestia mea, veți adăuga formularul de extindere param care nu a fost încă convertit de niciun alt răspuns care testează în mod explicit o variabilă shell pentru a fi setată – mă refer la
${var?not set}
– trecând testul respectiv și supraviețuind s-ar asigura că o variabilă potrivită cu*)
case
va da un răspuns definitiv, de exemplu. - Corecție – acest fapt, de fapt, ar răspunde la întrebarea adresată inițial, dar de atunci a fost editat în așa fel încât să schimbe fundamental sensul întrebării și, prin urmare, să invalideze răspunsul dvs.
- Aveți nevoie de
[[ $param = *[!\ ]* ]]
înmksh
.
Răspuns
POSIXly:
case $var in (*[![:blank:]]*) echo "$var contains non blank";; (*) echo "$var contains only blanks or is empty or unset" esac
Pentru a face diferența între blank , non-blank , gol , dezactivat :
case ${var+x$var} in (x) echo empty;; ("") echo unset;; (x*[![:blank:]]*) echo non-blank;; (*) echo blank esac
[:blank:]
este pentru caractere de spațiere orizontală (spațiu și filă în A SCII, dar probabil mai sunt câteva în localitatea dvs.; unele sisteme vor include spațiul neîntrerupt (acolo unde este disponibil), unele vor câștiga „t). Dacă doriți și caractere de spațiere verticală (cum ar fi linia nouă sau formularul), înlocuiți [:blank:]
cu [:space:]
.
Comentarii
- POSIXly este ideal, deoarece va funcționa cu (probabil mai bine) liniuță.
-
zsh
pare să aibă probleme cu[![:blank:]]
, crește:b
este modificator nevalid. În emulareash
șiksh
, evenimentul de creștere nu a fost găsit pentru[
- @cuonglm, ce ai încercat?
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
este OK pentru mine. Evenimentul care nu a fost găsit ar fi decât pentru shell-uri interactive. - @St é phaneChazelas: Ah, corect, am încercat cu shell-uri interactive.
:b
modificatorul invalid este un pic ciudat. - @FranklinYu, pe OS / X
sh
este construit cu--enable-xpg-echo-default
și--enable-strict-posix-default
astfel încât să fie conform Unix (care implicăecho '\t'
afișarea unei file).
Răspuns
Singurul motiv rău pentru a scrie un script shell, în loc de un script într-un bun limbaj de script, este dacă portabilitatea extremă este o preocupare majoră. > Moștenirea /bin/sh
este singurul lucru pe care îl puteți avea sigur, dar Perl, de exemplu, este mai probabil să fie disponibil pe mai multe platforme decât Bash. Prin urmare, nu scrieți niciodată scripturi shell care utilizează caracteristici care nu sunt „cu adevărat universale – și rețineți că mai mulți furnizori Unix proprietari și-au înghețat mediul shell înainte de POSIX.1-2001 .
Există un mod portabil de a face acest test, dar trebuie să utilizați tr
:
[ "x`printf "%s" "$var" | tr -d "$IFS"`" = x ]
(Valoarea implicită a $IFS
, în mod convenabil, este un spațiu, o filă și o linie nouă.)
(printf
builtin este el însuși foarte portabil, dar să te bazezi pe el este mult mai puțin dificil decât să afli ce variantă de echo
ai.)
Comentarii
- Că ‘ este un pic complicat.Modul obișnuit de a testa dacă un șir conține anumite caractere este cu
case
. - @Gilles Nu ‘ cred că este posibil ‘ să scrieți un
case
glob detectați un șir care este fie gol, fie conține numai caractere în spațiu. (Ar fi ușor cu o regexp, darcase
nu face regexps. Construcția din răspunsul dvs. a câștigat ‘ nu funcționează dacă vă pasă de linii noi.) - Am dat spații ca exemplu în răspunsul meu, deoarece ‘ este care este întrebarea a cerut. Este ‘ la fel de ușor de testat pentru caracterele spațiului alb:
case $param in *[![:space:]]*) …
. Dacă doriți să testați caractereleIFS
, puteți utiliza modelul*[$IFS]*
. - @mikeserv Într-un serios script defensiv, setați explicit IFS la
<space><tab><newline>
la început și apoi nu îl mai atingeți niciodată. Am crezut că ‘ ar fi o distragere a atenției. - În ceea ce privește variabilele din tipare, cred că funcționează în toate versiunile Bourne și toate shell-urile POSIX; ar necesita cod suplimentar pentru a detecta tiparele de cazuri și pentru a dezactiva expansiunea variabilă și nu pot ‘ să mă gândesc la un motiv pentru a o face. Am câteva exemple în
.profile
, care a fost executat de multe obuze Bourne. Desigur,[$IFS]
a câștigat ‘ să nu facă ceea ce se intenționa dacăIFS
are anumite elemente non-implicite valori (goale (sau nesetate), care conțin]
, începând cu!
sau^
) .
Răspuns
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
Comentarii
- acest lucru scapă de orice caracter de spațiu alb, nu doar de un singur spațiu, nu? mulțumesc
Răspuns
Pentru a testa dacă variabila este goală sau conține spații, puteți utiliza și acest cod:
${name:?variable is empty}
Comentarii
- Cred că răspunsul dvs. este votat în jos deoarece ” sau conține spații ” nu este adevărat.
- atenție – care ucide shell-ul curent. Mai bine să-l puneți într-un (: $ {subshell?}). De asemenea – care va scrie pe stderr – probabil că doriți redirecționare. Și cel mai important care evaluează valoarea reală a variabilei ‘ dacă nu este nesetată sau nulă. Dacă există ‘ o comandă acolo, tocmai ați executat-o. Este ‘ cel mai bine să rulați testul pe
:
. - cum va ucide shell-ul. și puteți testa, de asemenea, mai întâi definiți
name=aaaa
apoi executați această comandăecho ${name:?variable is empty}
va imprima valoarea numelui variabilei și acum executați această comandăecho ${name1:?variable is empty}
se va imprima -sh: name1: variabila este goală - Da –
echo ${name:?variable is empty}
fie va evalua la$name
‘ valoarea non-nulă sau va ucide shell-ul. Deci, din același motiv, nu ‘ nu faciprompt > $randomvar
și nu ar trebui să${var?}
– dacă ‘ este o comandă acolo, ‘ probabil va rula – și nu ‘ nu știu ce este. Un shell interactiv nu trebuie să iasă ‘ – motiv pentru care al tău nu ‘ t. Totuși, dacă doriți să vedeți câteva teste, există multe dintre ele aici. . Acesta nu este ‘ atât de lung …
Răspuns
Codul pe care l-ați postat [[ ! -z $param ]] && echo "I am not zero"
va imprima I am not zero
dacă parametrul este fie nesetat / nedefinit, fie gol (în bash, ksh și zsh).
To și tipăriți dacă parametrul conține doar spații (eliminați spațiile), POSIXly (pentru o gamă mai largă de cochilii):
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
Explicație:
- Un
${param# … }
elimină un text care conduce . - Textul principal este dat de:
${param%%[! ]*}
- Care se extinde la toate spațiile dinaintea orice caracter non-space , adică toate spațiile principale.
Rezultatul final al întregii expansiuni este eliminarea tuturor spațiilor principale.
Acest rezultat extins este testat dacă are lungimea 0.
- Dacă rezultatul este gol, atunci fie variabila a fost goală, fie
- eliminarea spațiilor principale a făcut-o goală.
Prin urmare, dacă testul este adevărat, variabila era deja goală sau avea doar spații în ea.
Conceptul este ușor de extins la mai multe tipuri de caractere. Pentru a include, de asemenea, file, plasați o filă explicită în expresia paranteză:
[ -z "${param#"${param%%[! ]*}"}" ] && echo "empty"
sau utilizați o variabilă cu caracterele pe care trebuie să le eliminați:
var=$" \t" # in ksh, bash, zsh [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"
sau puteți utiliza unele „expresii de clase de caractere” POSIX (gol înseamnă spațiu și filă):
[ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
Răspuns
Pentru a verifica dacă variabila are doar spații, inclusiv într-o variabilă multi-linie div id = „660e34d3e4”>
, încercați acest lucru:
[[ $var = *[$" \t\n"]* ]]
Sau cu xargs:
[[ -z $(echo $var | xargs) ]]
Sau cu sed:
[[ -z $(sed "/^$/d" <<< $var) ]]
Răspuns
Încercați acest lucru:
$ [[ -z \`echo $n\` ]] && echo zero zero
sed
au spus … doarecho
variabila pe care au spus-o …${var/pattern/string}
, atunci nu ar trebui să ‘ să fie[[ -z ${param/ /} ]]
cu spațiul dintre bare oblice să fie modelul și nimic după ce să fie șirul?[[ -z "${param// }" ]]
sigur arată capattern
este gol șireplacement string
este un spațiu unic. AH! Îl văd acumif pattern begins with a slash
Am ratat acea parte. deci modelul este/
, iar șirul este lăsat și, prin urmare, gol. Mulțumesc.