Comment puis-je tester si une variable est vide ou ne contient que des espaces?

La syntaxe bash suivante vérifie si param nest « pas vide:

 [[ ! -z $param ]] 

Par exemple:

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

Aucune sortie et cest bien.

Mais quand param est vide sauf pour un (ou plusieurs) caractères despacement, alors la casse est différente:

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

« Je ne suis pas zéro « est affiché.

Comment puis-je changer le test pour considérer les variables qui ne contiennent que des espaces comme vides?

Commentaires

  • De man test: -z STRING - the length of STRING is zero. Si vous souhaitez supprimer tous les espaces de $param, utilisez ${param// /}
  • WOW il ny a pas de fonction trim() intégrée à un * nix du tout? Tant de hacks différents pour réaliser quelque chose daussi simple …
  • @ADTC $ (sed ‘ s / ^ \ s + | \ s + $ // g ‘ < < < $ string) me semble assez simple. Pourquoi réinventer la roue?
  • Parce quelle pourrait être plus brillante
  • Il suffit de noter que [[ ! -z $param ]] équivaut à test ! -z $param.

Réponse

Tout dabord, notez que le -z test est explicitement pour:

la longueur de la chaîne est zéro

Autrement dit, une chaîne contenant uniquement des espaces ne doit pas soit vrai sous -z, car il a une longueur non nulle.

Ce que vous voulez, cest supprimer les espaces de la variable en utilisant le expansion des paramètres de remplacement de modèle :

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

Ceci étend le param et remplace toutes les correspondances du modèle (un seul espace) par rien, donc une chaîne qui ne contient que des espaces sera développée en un chaîne vide.


Le comment cela fonctionne est que ${var/pattern/string} remplace la première correspondance la plus longue de pattern par string. Lorsque pattern commence par / (comme ci-dessus), il remplace toutes les correspondances. Comme le remplacement est vide, nous pouvons omettre la valeur finale / et string:

$ {paramètre / modèle / chaîne}

Le modèle est développé pour produire un modèle comme dans le développement de nom de fichier. Le paramètre est développé et la plus longue correspondance de motif par rapport à sa valeur est remplacée par chaîne . Si pattern commence par «/», toutes les correspondances de pattern sont remplacées par string . Normalement, seule la première correspondance est remplacée. … Si string est nul, les correspondances de motif sont supprimées et le motif suivant peut être omis.

Après tout cela, nous nous retrouvons avec ${param// } pour supprimer tous les espaces.

Notez que cependant présent dans ksh (doù il provient), zsh et bash, cette syntaxe nest pas POSIX et ne doit pas être utilisé dans les scripts sh.

Commentaires

  • use sed ils ont dit … juste echo la variable quils ont dit …
  • Hmm. Si cest ${var/pattern/string} alors ‘ t-il [[ -z ${param/ /} ]] avec lespace entre les barres obliques être le modèle et rien après pour être la chaîne?
  • @JesseChisholm  » Parce que le remplacement est vide, nous pouvons omettre le final / et la valeur de chaîne « ;  » Si la chaîne est nulle, les correspondances du motif sont supprimées et le motif suivant peut être omis.  »
  • @MichaelHomer La réponse [[ -z "${param// }" ]] ressemble certainement à pattern est vide et replacement string est un seul espace. Ah! Je le vois maintenant if pattern begins with a slash Jai manqué cette partie. donc le modèle est / et la chaîne est laissée de côté et donc vide. Merci.
  • note de bash: si vous utilisez set -o nounset (set -u), et que param nest pas défini (plutôt que nul ou rempli despace), cela générera une erreur de variable indépendante. (set + u; …..) exempterait ce test.

Réponse

Le moyen le plus simple vérifier quune chaîne ne contient que des caractères dans un ensemble autorisé consiste à tester la présence de caractères non autorisés.Ainsi, au lieu de tester si la chaîne contient uniquement des espaces, testez si la chaîne contient un caractère autre que lespace. Dans bash, ksh ou zsh:

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

«Se compose despaces uniquement» inclut le cas dune variable vide (ou non définie).

Vous voudrez peut-être tester nimporte quel caractère despacement. Utilisez [[ $param = *[^[:space:]]* ]] pour utiliser les paramètres régionaux, ou toute autre liste explicite de caractères despaces que vous souhaitez tester, par exemple [[ $param = *[$" \t\n"]* ]] pour tester lespace, la tabulation ou la nouvelle ligne.

Faire correspondre une chaîne à un modèle avec = à lintérieur de [[ … ]] est une extension ksh (également présente dans bash et zsh). Dans nimporte quel style Bourne / POSIX, vous pouvez utiliser la construction case pour faire correspondre une chaîne à un modèle. Notez que les modèles de shell standard utilisent ! pour annuler un jeu de caractères, plutôt que ^ comme dans la plupart des syntaxes dexpressions régulières.

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

Pour tester les espaces blancs, la syntaxe $"…" est spécifique à ksh / bash / zsh; vous pouvez insérer ces caractères dans votre script littéralement (notez quune nouvelle ligne devra être entre guillemets, car barre oblique inverse + nouvelle ligne se développe en rien), ou les générer, par exemple

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

Commentaires

  • Cest presque excellent – mais, pour linstant, cela ne répond pas à la question comme posée. Il peut actuellement vous dire la différence entre une variable shell vide ou non définie et une qui ne contient que des espaces. Si vous acceptez ma suggestion, vous ajouterez la forme dexpansion des paramètres non encore convergée par une autre réponse qui teste explicitement une variable shell pour être définie – je veux dire ${var?not set} – en passant ce test et en survivant garantirait quune variable correspondant à votre *) case effectuerait une réponse définitive, par exemple.
  • Correction – cela, en fait, répondrait à la question posée à lorigine, mais elle a depuis été modifiée de telle manière quelle change fondamentalement le sens de la question et invalide donc votre réponse.
  • Vous avez besoin de [[ $param = *[!\ ]* ]] dans mksh.

Réponse

POSIXly:

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

Pour différencier vide , non vide , vide , non défini :

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

[:blank:] est pour les caractères despacement horizontal (espace et tabulation dans A SCII, mais il y en a probablement quelques autres dans votre locale; certains systèmes incluront lespace insécable (le cas échéant), dautres non « t). Si vous voulez également des caractères despacement vertical (comme le saut de ligne ou le saut de page), remplacez [:blank:] avec [:space:].

Commentaires

  • POSIXly est idéal car il fonctionnera avec le (sans doute mieux) tiret.
  • zsh semble avoir un problème avec [![:blank:]], il soulève :b est un modificateur non valide. Dans lémulation sh et ksh, lévénement déclenche un événement introuvable pour [
  • @cuonglm, quavez-vous essayé? var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac' est OK pour moi. Lévénement introuvable ne concernerait que les shells interactifs.
  • @St é phaneChazelas: Ah, cest vrai, jai essayé avec des shells interactifs. Le :b modificateur invalide est un peu étrange.
  • @FranklinYu, sous OS / X sh est construit avec --enable-xpg-echo-default et --enable-strict-posix-default afin dêtre compatible Unix (ce qui implique echo '\t' afficher un onglet).

Réponse

La seule raison restante décrire un script shell, au lieu dun script dans un langage de script bon , est si la portabilité extrême est une préoccupation majeure. Lhéritage /bin/sh est la seule chose dont vous pouvez être sûr, mais Perl, par exemple, est plus susceptible dêtre disponible multiplateforme que Bash. Par conséquent, nécrivez jamais de scripts shell qui utilisent des fonctionnalités qui ne sont pas vraiment universelles – et gardez à lesprit que plusieurs fournisseurs Unix propriétaires ont gelé leur environnement shell avant POSIX.1-2001 .

Il existe un moyen portable de faire ce test, mais vous devez utiliser tr:

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

(La valeur par défaut de $IFS, de manière pratique, est un espace, une tabulation et une nouvelle ligne.)

(Le printf intégré est lui-même spottly portable, mais sen remettre est beaucoup moins compliqué que de déterminer quelle variante de echo vous avez.)

Commentaires

  • Ce ‘ est un bit alambiqué.Le moyen portable habituel de tester si une chaîne contient certains caractères est avec case .
  • @Gilles Je ne ‘ Je ne pense pas quil ‘ est possible décrire un case glob à détecte une chaîne qui est soit vide, soit contient uniquement des espaces blancs. (Ce serait facile avec une expression régulière, mais case ne ‘ pas dexpressions rationnelles. La construction dans votre réponse ne vaut pas ‘ t fonctionne si vous vous souciez des sauts de ligne.)
  • Jai donné des espaces comme exemple dans ma réponse parce que ‘ est la question demandé. Il est également ‘ de tester les caractères d’espace blanc: case $param in *[![:space:]]*) …. Si vous souhaitez tester les caractères IFS, vous pouvez utiliser le modèle *[$IFS]*.
  • @mikeserv Dans un vraiment sérieusement script défensif, vous définissez explicitement IFS sur <space><tab><newline> au début et ne le touchez plus jamais. Je pensais que ‘ serait une distraction.
  • Concernant les variables dans les modèles, je pense que cela fonctionne dans toutes les versions de Bourne et tous les shells POSIX; il faudrait du code supplémentaire pour détecter les modèles de cas et désactiver lexpansion des variables et je ne peux ‘ penser à une raison de le faire. Jen ai quelques instances dans mon .profile qui a été exécuté par de nombreux shells Bourne. Bien sûr, [$IFS] a gagné ‘ t faire ce qui était prévu si IFS a certaines valeurs par défaut valeurs (vides (ou non définies), contenant ], commençant par ! ou ^) .

Réponse

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 

Commentaires

  • cela supprime tout caractère despace blanc, pas seulement un seul espace, non? merci

Réponse

Pour tester si la variable est vide ou contient des espaces, vous pouvez également utiliser ce code:

${name:?variable is empty} 

Commentaires

  • Je pense que votre réponse est rejetée car le  » ou contenir des espaces  » nest pas vrai.
  • soyez prudent – cela tue le shell actuel. Mieux vaut le mettre dans un (: $ {subshell?}). De plus – cela écrira dans stderr – vous voudrez probablement une redirection. Et le plus important qui évalue la valeur réelle de la variable ‘ si elle nest pas non définie ou nulle. Sil y a ‘ une commande là-dedans, vous venez de lexécuter. Il est ‘ dexécuter ce test sur :.
  • comment il va tuer le shell. et vous pouvez également tester cela, commencez par définir name=aaaa puis exécutez cette commande echo ${name:?variable is empty} elle affichera la valeur du nom de la variable et exécutera maintenant cette commande div id = « 6fe918cbc0 »>

il affichera -sh: name1: la variable est vide

  • Oui – echo ${name:?variable is empty} évaluera à $name ‘ la valeur non nulle ou il tuera le shell. Donc, pour la même raison, vous ‘ ne faites prompt > $randomvar que vous ne devriez ${var?} – si il y a ‘ une commande là-dedans, elle ‘ va probablement sexécuter – et vous ne ‘ t sais ce que cest. Un shell interactif n’a pas ‘ à quitter – c’est pourquoi le vôtre n ‘ t. Néanmoins, si vous voulez voir des tests, il y en a beaucoup ici. . Celui-ci nest ‘ pas assez long …
  • Réponse

    Le code que vous avez publié [[ ! -z $param ]] && echo "I am not zero" affichera I am not zero si param est soit non défini / non défini, soit vide (dans bash, ksh et zsh).

    Pour également print si le paramètre ne contient que des espaces (supprimer les espaces), POSIXly (pour un plus large éventail de shells):

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

    Explication:

    • Un ${param# … } supprime un texte principal .
    • Ce texte de début est donné par: ${param%%[! ]*}
    • Qui se développe en tous les espaces avant tout caractère autre quun espace , cest-à-dire tous les espaces de début.

    Le résultat final de toute lexpansion est que tous les espaces principaux sont supprimés.

    Ce résultat étendu est testé sil est de longueur 0.

    • Si le résultat est vide, alors soit la variable était vide, soit
    • en supprimant les espaces de début la rendu vide.

    Par conséquent, si le test est vrai, la variable était déjà vide ou ne contenait que des espaces.


    Le concept est facile à étendre à plus types de caractères. Pour inclure également des tabulations, placez une tabulation explicite à lintérieur de lexpression entre crochets:

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

    ou utilisez une variable avec les caractères que vous devez supprimer:

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

    ou vous pouvez utiliser une « expression de classe de caractères » POSIX (vide signifie espace et tabulation):

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

    Réponse

    Pour vérifier si la variable ne contient que des espaces, y compris dans une variable multiligne , essayez ceci:

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

    Ou avec xargs:

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

    Ou avec sed:

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

    Réponse

    Essayez ceci:

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

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *