Je voudrais vérifier si une chaîne commence par "node", par exemple "node001". Quelque chose comme
if [ $HOST == user* ]
then
echo yes
fi
Comment puis-je le faire correctement?
J'ai en outre besoin de combiner des expressions pour vérifier si HOST est "user1" ou commence par "node"
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
Comment puis-je le faire correctement?
Réponses:
Cet extrait du guide de script avancé de Bash dit:
Vous l'aviez donc presque correct; vous aviez besoin de crochets doubles , pas de crochets simples.
En ce qui concerne votre deuxième question, vous pouvez l'écrire de cette façon:
Qui fera écho
Il
if
est difficile de s'habituer à la syntaxe de Bash (IMO).la source
[[ $a == z* ]]
et[[ $a == "z*" ]]
? En d'autres termes: fonctionnent-ils différemment? Et que voulez-vous dire spécifiquement lorsque vous dites "$ a est égal à z *"?[[ $a == *com ]]
Si vous utilisez une version récente de Bash (v3 +), je suggère l'opérateur de comparaison d'expressions régulières Bash
=~
, par exemple,Pour faire correspondre
this or that
une expression régulière, utilisez|
, par exemple,Remarque - il s'agit d'une syntaxe d'expression régulière «correcte».
user*
signifieuse
et zéro ou plusieurs occurrences der
, doncuse
etuserrrr
correspondra.user.*
signifieuser
et zéro ou plusieurs occurrences de n'importe quel caractère, doncuser1
,userX
correspondra.^user.*
signifie correspondre au modèleuser.*
au début de $ HOST.Si vous n'êtes pas familier avec la syntaxe des expressions régulières, essayez de vous référer à cette ressource .
la source
=~
opérateur Bash ne fait correspondre les expressions régulières que lorsque le côté droit est UNQUOTED. Si vous citez le côté droit "Toute partie du motif peut être citée pour le forcer à correspondre en tant que chaîne." (1.) assurez-vous de toujours mettre les expressions régulières à droite sans guillemets et (2.) si vous stockez votre expression régulière dans une variable, assurez-vous de NE PAS citer le côté droit lorsque vous faites l'expansion des paramètres.J'essaie toujours de m'en tenir à POSIX
sh
au lieu d'utiliser des extensions Bash, car l'un des points majeurs du script est la portabilité (en plus de connecter des programmes, pas de les remplacer).Dans
sh
, il existe un moyen simple de rechercher une condition "is-prefix".Compte tenu de l'âge, des arcanes et de la cruauté de sh (et Bash n'est pas le remède: c'est plus compliqué, moins cohérent et moins portable), je voudrais souligner un très bel aspect fonctionnel: alors que certains éléments de syntaxe comme
case
sont intégrés , les constructions résultantes ne sont pas différentes de tout autre travail. Ils peuvent être composés de la même manière:Ou encore plus court
Ou encore plus court (juste pour présenter
!
comme un élément de langage - mais c'est un mauvais style maintenant)Si vous aimez être explicite, créez votre propre élément de langage:
N'est-ce pas vraiment sympa?
Et comme il ne
sh
s'agit essentiellement que de travaux et de listes de chaînes (et de processus internes, à partir desquels les travaux sont composés), nous pouvons même maintenant faire une programmation fonctionnelle légère:C'est élégant. Ce n'est pas que je recommanderais d'utiliser
sh
quoi que ce soit de sérieux - cela casse trop rapidement les exigences du monde réel (pas de lambdas, nous devons donc utiliser des chaînes. Mais l'imbrication des appels de fonction avec des chaînes n'est pas possible, les tuyaux ne sont pas possibles, etc.)la source
case $HOST in user01 | node* ) ...
if case $HOST in node*) true;; *) false;; esac; then
Je l'ai vu ici et là, à mes yeux, il semble un peu froissé.case
commandes becaues sont des commandes, elles peuvent aller à l'intérieurif ... then
.beginswith() { case "$2" in "$1"*) true;; *) false;; esac; }
autrement s'il$1
a un littéral*
ou?
il pourrait donner une mauvaise réponse.Vous pouvez sélectionner uniquement la partie de la chaîne que vous souhaitez vérifier:
Pour votre question de suivi, vous pouvez utiliser un OU :
la source
${HOST:0:4}
HOST='a b'; if [ ${HOST:0:4} = user ] ; then echo YES ; fi
Je préfère les autres méthodes déjà publiées, mais certaines personnes aiment utiliser:
Éditer:
J'ai ajouté vos suppléants à la déclaration de cas ci-dessus
Dans votre version modifiée, vous avez trop de crochets. Ça devrait ressembler à ça:
la source
Bien que je trouve la plupart des réponses ici tout à fait correctes, beaucoup d'entre elles contiennent des bashismes inutiles. L'extension des paramètres POSIX vous offre tout ce dont vous avez besoin:
et
${var#expr}
bandes le plus petit préfixe correspondantexpr
de${var}
et des rentabilités. Par conséquent, si${host}
ne commence pas paruser
(node
),${host#user}
(${host#node}
) est identique à${host}
.expr
permet lesfnmatch()
caractères génériques, ainsi${host#node??}
et les amis travaillent également.la source
[[ $host == user* ]]
pourrait être nécessaire, car il est beaucoup plus lisible que[ "${host#user}" != "${host}" ]
. En tant que tel, à condition que vous contrôliez l'environnement dans lequel le script est exécuté (ciblez les dernières versions debash
), le premier est préférable.has_prefix()
fonction et ne plus jamais le regarder.Depuis
#
a un sens dans Bash, je suis arrivé à la solution suivante.De plus, j'aime mieux emballer les chaînes avec "" pour surmonter les espaces, etc.
la source
blah:
, on dirait que c'est la réponse!Ajout d'un tout petit peu plus de détails de syntaxe à la réponse la plus élevée de Mark Rushakoff.
L'expression
Peut également s'écrire
L'effet est le même. Assurez-vous simplement que le caractère générique est en dehors du texte cité. Si le caractère générique est à l' intérieur des guillemets, il sera interprété littéralement (c'est-à-dire pas comme un caractère générique).
la source
@OP, pour vos deux questions, vous pouvez utiliser case / esac:
Deuxième question
Ou Bash 4.0
la source
;&
n'est disponible que dans Bash> = 4.ne fonctionne pas, parce que tous
[
,[[
ettest
reconnaître la même grammaire nonrecursive. Voir la section EXPRESSIONS CONDITIONNELLES sur votre page de manuel Bash.En passant, le SUSv3 dit
Vous devez l'écrire de cette façon, mais le test ne le prend pas en charge:
test utilise = pour l'égalité des chaînes, et plus important encore, il ne prend pas en charge la correspondance de modèles.
case
/esac
a un bon support pour la correspondance de motifs:Il a l'avantage supplémentaire de ne pas dépendre de Bash, et la syntaxe est portable. De la spécification Unix unique , le langage de commande Shell :
la source
[
ettest
sont intégrés Bash ainsi que des programmes externes. Essayeztype -a [
.if [ -z $aa -or -z $bb ]
; ... donne " bash: [: -ou: opérateur binaire attendu ";if [ -z "$aa" -o -z "$bb" ] ; ...
passe cependant .grep
Oubliant les performances, c'est POSIX et plus joli que les
case
solutions:Explication:
printf '%s'
pour empêcher l'printf
expansion des échappements antislash: chaîne verbatim littérale Bash printfgrep -q
empêche l'écho des correspondances avec stdout: comment vérifier si un fichier contient une chaîne spécifique à l'aide de Bashgrep -E
active les expressions régulières étendues, dont nous avons besoin pour la^
la source
J'ai modifié la réponse de @ markrushakoff pour en faire une fonction appelable:
Utilisez-le comme ceci:
Voici une version plus complexe qui prévoit une valeur par défaut spécifiée:
Utilisez-le comme ceci:
la source
Une autre chose que vous pouvez faire est de
cat
savoir avec quoi vous faites écho etinline cut -c 1-1
la source