bash: testez si $ WORD est dans lensemble

Je recherche une construction dans bash, pour décider si une variable $WORD est lun des mots définis. Jai besoin de quelque chose comme ceci:

if "$WORD" in dog cat horse ; then echo yes else echo no fi 

est-ce que bash a une telle construction? Sinon, quelle serait la solution la plus proche?

Réponse

Il sagit dune solution Bash uniquement (> = version 3) qui utilise des expressions régulières:

if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi 

Si votre liste de mots est longue, vous pouvez la stocker dans un fichier (un mot par ligne) et faire ceci:

if [[ "$WORD" =~ $(echo ^\($(paste -sd"|" /your/file)\)$) ]]; then echo "$WORD is in the list" else echo "$WORD is not in the list" fi 

Une mise en garde avec lapproche de fichier:

  • Il se cassera si le fichier a des espaces. Cela peut être corrigé par quelque chose comme:

    sed "s/[[:blank:]]//g" /your/file | paste -sd "|" /dev/stdin 

Merci à @terdon de mavoir rappelé dancrer correctement le modèle avec ^ et $.

Commentaires

  • Et shopt -s nocasematch peut vous aider si vous voulez que la recherche ne respecte pas la casse.
  • Notez que vous devez utiliser [[ et ]][ et ] ne suffisent pas.
  • Je cherchais pour un ‘ oneliner ‘ pour valider mon argument de script, et cela a parfaitement fonctionné. Merci! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
  • Si vous ‘ allez mettre votre liste de correspondances dans un fichier, vous pouvez aussi bien utiliser grep: egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK".

Réponse

case $word in dog|cat|horse) echo yes;; *) echo no;; esac 

Réponse

Que diriez-vous:

#!/usr/bin/env bash WORD="$1" for w in dog cat horse do if [ "$w" == "$WORD" ] then yes=1 break fi done; [ "$yes" == "1" ] && echo "$WORD is in the list" || echo "$WORD is not in the list" 

Ensuite:

$ a.sh cat cat is in the list $ a.sh bob bob is not in the list 

Réponse

if (echo "$set" | fgrep -q "$WORD") 

Commentaires

  • Attention cependant, cela retournera true si $WORD est vide, il correspondra si WORD=ca ou WORD=og ou similaire et je suppose que vous vouliez dire echo ${set[@]}.
  • il suffit dajouter -w à grep pour éviter les mots partiels

Réponse

Vous pouvez définir une fonction bash pour ceci:

function word_valid() { if [ "$1" != "cat" -a "$1" != "dog" -a "$1" != "horse" ];then echo no else echo yes fi } 

Ensuite, utilisez simplement comme ceci:

word_valid cat 

Réponse

Je cherchais une solution « une ligne » pour valider mon argument de script, et jai utilisé Joseph R. answer ci-dessus à venir avec:

[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }

Réponse

Vous pourrait utiliser fgrep pour spécifier tous les mots autorisés:

if $(echo "$WORD" | fgrep -wq -e dog -e cat -e horse) ; then echo yes else echo no fi 

Lindicateur -w correspond uniquement aux mots complets, le -q le fait fonctionner en silence (car tout ce dont nous avons besoin est la valeur de retour pour linstruction if à utiliser), et chaque motif -e spécifie un modèle pour autoriser.

fgrep est la version de grep qui effectue une correspondance de chaîne normale au lieu dune correspondance regex. Si vous avez grep, vous devriez avoir fgrep, mais sinon, cest « identique à lutilisation de grep avec lindicateur -F (il suffit donc de remplacer fgrep -wq ci-dessus par grep -Fwq).

Réponse

Cela a fonctionné pour moi:

#!/bin/bash phrase=(cat dog parrot cow horse) findthis=parrot for item in ${phrase[*]} do test "$item" == "$findthis" && { echo "$findthis found!"; break; } done 

Réponse

Vous voudrez peut-être mettre la liste de mots dans un fichier, au cas où vous changeriez souvent la liste, ou si vous le souhaitez être partagée par plusieurs scripts. Et vous devrez peut-être mettre les mots dans un fichier si la liste devient trop longue à gérer dans un script. Ensuite, vous pouvez dire

if fgrep –qx "$WORD" word_list 

Commentaires

  • non, je ne ‘ ne veux pas avoir ma liste dans un fichier

Réponse

Si les mots sont une liste où les valeurs sont séparées par une nouvelle ligne, vous pouvez faire:

WORDS="$(ls -1)" if echo "${WORDS}" | grep --quiet --line-regexp --fixed-strings "${WORD}"; then echo yes else echo no fi 

Réponse

Jai juste eu le même problème et jai trouvé une solution étonnamment compréhensible qui ne nécessite aucune connaissance des regex.

Veuillez noter que le La solution illustrée ci-dessous peut être uniquement bash, car je nai aucune idée des différences entre bash et les autres shells. De plus, le manuel bash avertit que ce type de correspondance de modèle est lent si la chaîne à rechercher est longue.

WORD=abc [[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set. 

Comment cela fonctionne-t-il?Je ne veux pas répéter de grandes parties du manuel bash ici, mais en mes propres termes:

Si lopérateur binaire == est utilisé avec la commande composée [[, le mot situé à droite de lopérateur subit une correspondance de modèle comme expliqué dans la section  » Correspondance de modèle  » dans le manuel bash. De plus, dans ces conditions, lors de la correspondance, loption shell extglob est supposée être définie (quel que soit le paramètre réel); cest le point clé pour comprendre ce qui précède.

Mais que se passe-t-il si les mots de votre ensemble contiennent déjà des caractères qui ont une signification particulière dans la correspondance de motifs, la substitution de commandes et autres extensions? Le remède est simple: utilisez simplement quelque chose comme

[[ "$WORD" == @("a*"|abc|"?ghi"|"$DontExpandMe"|barbaz) ]] && echo Word is in set. 

Jai trouvé que cétait très simple, compréhensible et efficace (tant que $WORD est court) solution qui na pas deffets secondaires ou est da ngerous comme les méthodes basées sur set.

Laisser un commentaire

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