Question Dans bash, comment puis-je vérifier si une chaîne commence avec une certaine valeur?


Je voudrais vérifier si une chaîne commence par "noeud" par ex. "node001". Quelque chose comme

if [ $HOST == user* ]  
  then  
  echo yes  
fi

Comment puis-je le faire correctement?


J'ai besoin en outre de combiner des expressions pour vérifier si HOST est soit "user1" ou commence par "node"

if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];  
then  
echo yes 
fi

> > > -bash: [: too many arguments

Comment le faire correctement?


515
2018-01-31 16:12


origine


Réponses:


Cet extrait sur le Guide de script Advanced Bash dit:

# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.

[[ $a == z* ]]   # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

Donc vous l'avez eu presque correct; vous aviez besoin double parenthèses, pas des parenthèses simples.


En ce qui concerne votre deuxième question, vous pouvez l'écrire de cette façon:

HOST=user1
if  [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
    echo yes1
fi

HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
    echo yes2
fi

Ce qui fera écho

yes1
yes2

Bash's if la syntaxe est difficile à s'habituer à (IMO).


711
2018-01-31 16:16



Si vous utilisez un bash récent (v3 +), suggérez bash opérateur de comparaison regex =~, c'est à dire.

if [[ "$HOST" =~ ^user.* ]]; then
    echo "yes"
fi

Correspondre this or that dans une utilisation regex |, c'est à dire.

if [[ "$HOST" =~ ^user.*|^host1 ]]; then
    echo "yes"
fi

Remarque: il s'agit de la syntaxe d'expression régulière "appropriée".

  • user* veux dire use et zéro ou plusieurs occurrences de r, alors use et userrrr va correspondre.
  • user.* veux dire user et zéro-ou-plus occurrences de n'importe quel caractère, de sorte user1, userX va correspondre.
  • ^user.* signifie correspondre au modèle user.* au début de $ HOST.

Si vous n'êtes pas familier avec la syntaxe d'expression régulière, essayez de vous référer à cette ressource.

Remarque - il est préférable de poser chaque nouvelle question comme une nouvelle question, de rendre le stackoverflow plus ordonné et plus utile. Vous pouvez toujours inclure un lien vers une question précédente pour référence.


139
2018-01-31 16:15



J'essaie toujours de rester avec POSIX sh au lieu d'utiliser des extensions bash, car la portabilité est l'un des principaux points de script. (Outre de liaison programmes, ne pas les remplacer)

Dans sh, il y a un moyen facile de vérifier une condition "is-prefix".

case $HOST in node*)
    your code here
esac

Étant donné l'âge, l'arcane et le crush sh (et bash n'est pas le remède: c'est plus compliqué, moins cohérent et moins portable), je tiens à 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 toutes les autres tâches. Ils peuvent être composés de la même manière:

if case $HOST in node*) true;; *) false;; esac; then
    your code here
fi

Ou même plus court

if case $HOST in node*) ;; *) false;; esac; then
    your code here
fi

Ou même plus court (juste pour présenter ! en tant qu'élément de langage - mais c'est un mauvais style maintenant)

if ! case $HOST in node*) false;; esac; then
    your code here
fi

Si vous aimez être explicite, créez votre propre élément de langue:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }

N'est-ce pas plutôt sympa?

if beginswith node "$HOST"; then
    your code here
fi

Et comme sh est fondamentalement uniquement des jobs et des listes de chaînes (et des processus internes, à partir desquels des jobs sont composés), nous pouvons même maintenant faire de la programmation fonctionnelle légère:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }

all() {
    test=$1; shift
    for i in "$@"; do
        $test "$i" || return
    done
}

all "beginswith x" x xy xyz ; checkresult  # prints TRUE
all "beginswith x" x xy abc ; checkresult  # prints FALSE

C'est élégant. Pas que je préconise d'utiliser sh pour quelque chose de sérieux - il casse trop vite sur les exigences du monde réel (pas de lambdas, donc il faut utiliser des chaînes.) Mais imbriquer des fonctions avec des chaînes n'est pas possible, les pipes ne sont pas possibles ...)


73
2017-09-01 13:26



Vous pouvez sélectionner uniquement la partie de la chaîne que vous souhaitez vérifier:

if [ ${HOST:0:4} = user ]

Pour votre question de suivi, vous pouvez utiliser un OU:

if [[ $HOST == user1 || $HOST == node* ]]

55
2018-01-31 16:15



Je préfère les autres méthodes déjà postées, mais certaines personnes aiment utiliser:

case "$HOST" in 
    user1|node*) 
            echo "yes";;
        *)
            echo "no";;
esac

Modifier:

J'ai ajouté vos suppléants à l'énoncé de cas ci-dessus

Dans votre version éditée, vous avez trop de crochets. Ça devrait ressembler à ça:

if [[ $HOST == user1 || $HOST == node* ]];

53
2018-01-31 16:29



puisque # a une signification dans bash je suis arrivé à la solution suivante.
En plus je préfère emballer des cordes avec "" pour surmonter des espaces etc.

A="#sdfs"
if [[ "$A" == "#"* ]];then
    echo "skip comment line"
fi

26
2017-11-01 09:11



Bien que je trouve la plupart des réponses ici tout à fait correctes, beaucoup d'entre elles contiennent des bashismes inutiles. Extension de paramètre POSIX vous donne tout ce dont vous avez besoin:

[ "${host#user}" != "${host}" ]

et

[ "${host#node}" != "${host}" ]

${var#expr} dépouille le plus petit préfixe correspondant expr de ${var} et renvoie cela. Par conséquent si ${host} Est-ce que ne pas Commencer avec user (node), ${host#user} (${host#node}) est le même que ${host}.

expr permet fnmatch() jokers, donc ${host#node??} et les amis travaillent aussi.


21
2018-05-06 13:02