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
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 siWORD=ca
ouWORD=og
ou similaire et je suppose que vous vouliez direecho ${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
.
shopt -s nocasematch
peut vous aider si vous voulez que la recherche ne respecte pas la casse.[[
et]]
–[
et]
ne suffisent pas.[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK"
.