52

I am looking for a construct in bash, to decide if a variable $WORD is one of defined words. I need something like this:

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

does bash have such construct? If not, what would be the closest?

10 Answers 10

52

This is a Bash-only (>= version 3) solution that uses regular expressions:

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

If your word list is long, you can store it in a file (one word per line) and do this:

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

One caveat with the file approach:

  • It will break if the file has whitespace. This can be remedied by something like:

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

Thanks to @terdon for reminding me to properly anchor the pattern with ^ and $.

  • 1
    And shopt -s nocasematch might help if you want the search to be case insensitive. – Skippy le Grand Gourou Feb 13 '14 at 16:27
  • 1
    Note that you have to use [[ and ]] - [ and ] are not enough. – Greg Dubicki Aug 26 '16 at 11:28
  • i was searching for a 'oneliner' to validate my script argument, and this worked perfectly. thank you! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; } – RASG May 17 '17 at 11:20
71
case $word in
    dog|cat|horse) echo yes;;
    *)             echo no;;
esac
11

How about:

#!/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"

Then:

$ a.sh cat
cat is in the list
$ a.sh bob
bob is not in the list
3
if (echo "$set"  | fgrep -q "$WORD")
  • 1
    Careful though, this will return true if $WORD is empty, it will match if WORD=ca or WORD=og or similar and I assume you meant echo ${set[@]}. – terdon Jan 29 '14 at 18:25
  • just add -w to grep to avoid partial words – BrenoZan Jan 29 '14 at 18:34
1

You could define a bash function for this:

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

Then use simply like this:

word_valid cat
1

i was searching for a 'one line' solution to validate my script argument, and used Joseph R. answer above to come up with:

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

0

This worked for me:

#!/bin/bash
phrase=(cat dog parrot cow horse)
findthis=parrot

for item in ${phrase[*]}
do
    test "$item" == "$findthis" && { echo "$findthis found!"; break; }
done
0

You may want to put the list of words into a file, in case you change the list often, or you want it to be shared by multiple scripts.  And you may need to put the words into a file if the list gets too long to manage in a script.  Then you can say

if fgrep –qx "$WORD" word_list
  • no, I don't want to have my list in a file – Martin Vegter Jan 30 '14 at 9:30
0

If words are a list where values are separated by a newline, you can do:

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

You could use fgrep to specify all allowed words:

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

The -w flag matches only full words, the -q flag makes it operate silently (because all we need is the return value for the if statement to use), and each -e pattern specifies a pattern to allow.

fgrep is the version of grep that does normal string matching instead of regex matching. If you have grep, you should have fgrep, but if not, it's identical to using grep with the -F flag (so you would just replace fgrep -wq above with grep -Fwq).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.