bash: teste si $ WORD est dans le set

54

Je cherche une construction dans bash, pour décider si une variable $WORDest un mot défini. J'ai besoin de quelque chose comme ça:

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

bash a-t-il une telle construction? Si non, quel serait le plus proche?

Martin Vegter
la source

Réponses:

57

Ceci est une 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 procéder ainsi:

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 l'approche de fichier:

  • Cela cassera si le fichier a des espaces. On peut remédier à cela par quelque chose comme:

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

Merci à @terdon de me rappeler de bien ancrer le motif avec ^et $.

Joseph R.
la source
1
Et shopt -s nocasematchpourrait aider si vous souhaitez que la recherche soit insensible à la casse.
Skippy le Grand Gourou
1
Notez que vous devez utiliser [[et ]]- [et ]ne suffisent pas.
Greg Dubicki
Je cherchais un 'oneliner' pour valider mon argument de script, et cela fonctionnait parfaitement. Merci! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
RASG
76
case $word in
    dog|cat|horse) echo yes;;
    *)             echo no;;
esac
John Kugelman soutient Monica
la source
11

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
terdon
la source
3
if (echo "$set"  | fgrep -q "$WORD")
BrenoZan
la source
1
Attention, cela retournera vrai si $WORDest vide, il correspondra si WORD=caou WORD=ogou similaire et je suppose que vous vouliez dire echo ${set[@]}.
terdon
ajoutez simplement -w à grep pour éviter les mots partiels
BrenoZan
1

Vous pouvez définir une fonction bash pour cela:

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
suspect
la source
1

Je cherchais une solution «une ligne» pour valider mon argument de script et utilisais la réponse de Joseph R. ci-dessus pour trouver:

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

RASG
la source
0

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
Javier
la source
0

Vous voudrez peut-être mettre la liste de mots dans un fichier si vous la modifiez souvent ou si vous souhaitez que plusieurs scripts la partagent. Et vous devrez peut-être mettre les mots dans un fichier si la liste est trop longue à gérer dans un script. Alors tu peux dire

if fgrep qx "$WORD" word_list
Scott
la source
non, je ne veux pas avoir ma liste dans un fichier
Martin Vegter le
0

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
Mitar
la source
0

Vous pouvez 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

Le -wdrapeau ne correspond qu'à des mots entiers, il le -qfait fonctionner de manière silencieuse (car tout ce dont nous avons besoin est la valeur de retour de l'instruction if à utiliser) et chaque -emodèle spécifie un modèle à autoriser.

fgrepest la version de grep qui effectue la correspondance normale des chaînes au lieu de la correspondance régulière. Si vous avez grep, vous devriez avoir fgrep, mais sinon, c'est identique à utiliser grepavec le -Fdrapeau (afin que vous remplaciez simplement fgrep -wqci-dessus avec grep -Fwq).

Christopher Shroba
la source