La syntaxe bash suivante vérifie si elle param
n'est pas vide:
[[ ! -z $param ]]
Par exemple:
param=""
[[ ! -z $param ]] && echo "I am not zero"
Pas de sortie et c'est bien.
Mais quand param
est vide sauf pour un (ou plusieurs) espace, le cas est différent:
param=" " # one space
[[ ! -z $param ]] && echo "I am not zero"
"Je ne suis pas zéro" est sorti.
Comment puis-je modifier le test pour considérer les variables qui ne contiennent que des espaces, vides?
bash
shell
shell-script
string
maihabunash
la source
la source
man test
:-z STRING - the length of STRING is zero
. Si vous souhaitez supprimer tous les espaces$param
, utilisez${param// /}
trim()
fonction simple intégrée à aucun * nix du tout? Autant de trucs différents pour réaliser quelque chose d'aussi simple ...[[ ! -z $param ]]
équivaut àtest ! -z $param
.Réponses:
Tout d'abord, notez que le
-z
test est explicitement pour:Autrement dit, une chaîne ne contenant que des espaces ne doit pas être vraie sous
-z
, car elle a une longueur non nulle.Ce que vous voulez, c'est supprimer les espaces de la variable à l'aide de l' extension de paramètre de remplacement de modèle :
Cela développe la
param
variable et remplace toutes les correspondances du modèle(un seul espace) par rien. Ainsi, une chaîne contenant uniquement des espaces sera développée en une chaîne vide.
La façon dont cela fonctionne est de
${var/pattern/string}
remplacer le premier match le plus long depattern
avecstring
. Quandpattern
commence par/
(comme ci-dessus), il remplace toutes les correspondances. Comme le remplacement est vide, nous pouvons omettre le final/
et lastring
valeur:Après tout cela, on finit par
${param// }
supprimer tous les espaces.Notez que, bien qu’elle soit présente dans
ksh
(où elle a son origine),zsh
etbash
que cette syntaxe n’est pas POSIX, elle ne doit pas être utilisée dans lessh
scripts.la source
sed
ils ont dit ... justeecho
la variable ils ont dit ...${var/pattern/string}
cas, ne devriez-vous pas laisser[[ -z ${param/ /} ]]
l'espace entre les barres obliques être le motif et rien après la chaîne?[[ -z "${param// }" ]]
sûre, lepattern
est vide et lereplacement string
est un seul espace. AH! Je le vois maintenantif pattern begins with a slash
j'ai raté cette partie. le motif est donc/
et la chaîne est laissée et donc vide. Merci.Le moyen le plus simple de vérifier qu’une chaîne ne contient que des caractères d’un ensemble autorisé consiste à vérifier la présence de caractères non autorisés. Ainsi, au lieu de vérifier si la chaîne contient uniquement des espaces, vérifiez si la chaîne contient un caractère autre que l'espace. En bash, ksh ou zsh:
«Ne contient que des espaces» inclut le cas d'une variable vide (ou non définie).
Vous voudrez peut-être tester n'importe quel caractère d'espacement. Utilisez-le
[[ $param = *[^[:space:]]* ]]
pour utiliser les paramètres régionaux ou la liste explicite de caractères d'espaces que vous souhaitez tester, par exemple[[ $param = *[$' \t\n']* ]]
pour tester l'espace, la tabulation ou la nouvelle ligne.Faire correspondre une chaîne avec un motif à l'
=
intérieur[[ … ]]
est une extension ksh (également présente dans bash et zsh). Dans n'importe quel style Bourne / POSIX, vous pouvez utiliser lacase
construction pour faire correspondre une chaîne à un modèle. Notez que les modèles de shell standard utilisent!
pour nier un jeu de caractères, plutôt que^
dans la plupart des syntaxes d'expression régulières.Pour tester les caractères d'espacement, la
$'…'
syntaxe est spécifique à ksh / bash / zsh; vous pouvez insérer ces caractères dans votre script de manière littérale (notez qu'un retour à la ligne doit être placé entre guillemets, car la barre oblique inverse + le trait nouveau est réduit à néant), ou les générer, par exemplela source
${var?not set}
: la réussite de ce test et sa survie garantiraient qu’une variable correspondant à votre*)
case
produirait un résultat définitif. répondre, par exemple.[[ $param = *[!\ ]* ]]
demksh
.POSIXly:
Pour différencier les espaces vides , non vides , vides et non définis :
[:blank:]
est pour les caractères d'espacement horizontal (espace et tabulation en ASCII, mais il y en a probablement quelques autres dans vos paramètres régionaux; certains systèmes incluent l'espace insécable (le cas échéant), d'autres non). Si vous souhaitez également utiliser des caractères d'espacement vertical (comme une nouvelle ligne ou un saut de formulaire), remplacez-le[:blank:]
par[:space:]
.la source
zsh
semble avoir un problème avec[![:blank:]]
, elle:b
est un modificateur invalide. Danssh
etksh
imiter, il soulève événement non trouvé pour[
var=foo zsh -c 'case ${var+x$var} in (x*[![:blank:]]*) echo x; esac'
est ok pour moi. L'événement non trouvé ne concernerait que des coques interactives.:b
modificateur invalide est un peu étrange.sh
estbash
construit avec--enable-xpg-echo-default
et de--enable-strict-posix-default
manière à être conforme à Unix (ce qui implique laecho '\t'
sortie d'un onglet).La seule raison qui reste pour écrire un script shell plutôt qu'un script dans un bon langage de script est si la portabilité extrême est une préoccupation primordiale. L'héritage
/bin/sh
est la seule chose dont vous pouvez être certain, mais Perl, par exemple, est plus susceptible d'être disponible sur plusieurs plates-formes que Bash. Par conséquent, n'écrivez jamais de scripts shell utilisant des fonctionnalités qui ne sont pas vraiment universelles - et gardez à l'esprit 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
:(La valeur par défaut
$IFS
, commodément, est un espace, un onglet et une nouvelle ligne.)(La fonction
printf
intégrée est elle-même assez portable, mais il est beaucoup plus simple de s'y fier que de déterminer quelle varianteecho
vous avez.)la source
case
.case
glob pour détecter une chaîne vide ou contenant uniquement des caractères d'espacement. (Ce serait facile avec une expression rationnelle, mais cecase
n'est pas le cas. La construction de votre réponse ne fonctionnera pas si vous vous souciez des nouvelles lignes.)case $param in *[![:space:]]*) …
. Si vous souhaitez tester lesIFS
caractères, vous pouvez utiliser le modèle*[$IFS]*
.<space><tab><newline>
au début et ne le touchez plus jamais. Je pensais que ce serait une distraction..profile
qui ont été exécutés par de nombreux obus Bourne. Bien sûr[$IFS]
, ne fera pas ce qui était prévu siIFS
certaines valeurs autres que celles par défaut (vide (ou non définie), contenant]
, commençant par!
ou^
) sont présentes.la source
Pour tester si la variable est vide ou contient des espaces, vous pouvez également utiliser ce code:
la source
:
.name=aaaa
puis exécutez cette commande ,echo ${name:?variable is empty}
il affiche la valeur de nom de variable et maintenant exécuter cette commande ,echo ${name1:?variable is empty}
il imprimera -SH: nom1: variable est videecho ${name:?variable is empty}
évaluera soit la$name
valeur non-nulle de s ou tuera le shell. Donc, pour la même raison, vous ne le ferez pasprompt > $randomvar
non plus${var?}
- s'il y a une commande, elle va probablement s'exécuter - et vous ne savez pas ce que c'est. Un shell interactif n'a pas à sortir - c'est pourquoi le vôtre ne le fait pas. Néanmoins, si vous voulez voir des tests, il y en a beaucoup ici. . Celui-ci n'est pas aussi long ...Pour tester si une variable est non définie, vide (a une valeur nulle) ou ne contient que des espaces:
Explication:
${param%%[! ]*}
supprime du premier non-espace à la fin.-z
, alors échoempty
.Ce qui précède est compatible POSIX et s’applique à n’importe quel descendant de Bourne.
Si vous souhaitez étendre cela aussi aux onglets, incluez un onglet explicite:
ou utilisez une variable avec les caractères à supprimer:
ou vous pouvez utiliser une "expression de classe de caractère" POSIX (vide signifie espace et tabulation):
Mais cela échouera dans mksh, lksh et chic.
la source
Essaye ça:
la source