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
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 = *[!\ ]* ]]
dansmksh
.
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émulationsh
etksh
, 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 impliqueecho '\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, maiscase
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èresIFS
, 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 siIFS
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 commandeecho ${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
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
sed
ils ont dit … justeecho
la variable quils ont dit …${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?[[ -z "${param// }" ]]
ressemble certainement àpattern
est vide etreplacement string
est un seul espace. Ah! Je le vois maintenantif 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.