2

I have a variable $FOO with values one two three.

echo $FOO
one two three

Is there a way in bash to check if two exists and exactly matches one of the values of $FOO

I can do this

if [[ "two" =~ ^(one|two|three)$ ]]; then
    echo "two is in the list"
else
    echo "two is not in the list"
fi

And it works, but I'd like to check using the actual variable $FOO and not (one|two|three)$

Is this possible?

Metro
  • 873
  • 8
  • 19
  • define *`exactly matches`*; do you mean it has to match a 'word', eg, you would *not* get a match if `FOO='one 1two3 three'`? – markp-fuso Jan 28 '22 at 20:20
  • You can use [word boundaries](https://stackoverflow.com/questions/9792702/does-bash-support-word-boundary-regular-expressions), or perhaps like `if [[ "$FOO" =~ (^| )two($| ) ]]; then` – The fourth bird Jan 28 '22 at 20:25
  • Yes. No partial matches. So `twoo` or `two1` should not match. Only `two` – Metro Jan 28 '22 at 20:29

7 Answers7

2

If the items in $FOO are guaranteed to be separated by spaces, you can use this:

if [[ " $FOO " = *" $TWO "* ]]; then
    ...

Note that this reverses the roles of $FOO and $TWO from what you might expect; it treats $FOO as the string to check against a pattern, and the pattern is essentially "something that contains $TWO". It also adds explicit spaces to $TWO to make sure it matches only full items, and similarly adds spaces around $FOO so that'll match the first and last items in it.

If the delimiters in $FOO might be tabs or other space-like characters, you can use this more complex pattern:

if [[ " $FOO " = *[[:space:]]"$TWO"[[:space:]]* ]]; then
Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
0

Heres how to do it below

FOO='one two three'
TWO='two'
if [[ "$FOO" == *"$TWO"* ]]; then
  echo "two is in the list"
fi

wildcard aka * is a symbol used to represent zero, one or more characters.

carlosdafield
  • 1,479
  • 5
  • 16
0

Using an array

$ FOO=(one two three)
$ n=0;while [[ $n -lt ${#FOO} ]]; do  [[ "${FOO[$n]}" == "two" ]] && echo "two is in the list"; n=$(( $n + 1 )); done
two is in the list
HatLess
  • 10,622
  • 5
  • 14
  • 32
0

You can construct pattern with :

foo=(one two three)
pattern="^($(IFS="|"; echo "${foo[*]}"))\$"

if  [[ two =~ $pattern ]]; then
    echo "two is in the list"
else
    echo "two is not in the list"
fi
Philippe
  • 20,025
  • 2
  • 23
  • 32
0

It's odd that nobody posted case. It's the simplest and most portable. Notice the added spaces around $FOO.

case " $FOO " in
*" two "*) echo two is in the list; ;;
*) echo two is not in the list; ;;
esac
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
-1

You can try something like this

FOO="one two three"

foo=( $FOO )

if [[ "${foo[*]}" =~ ' two ' ]]
then
    echo "two is in the list"
else
    echo "two is not in the list"
fi

which will work for the simple cases (i.e. no spaces in the values)

Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • This won't match if `two` begins or ends the list. There's also no point in creating an array only to create a new string from the array immediately. – chepner Jan 28 '22 at 20:28
-1

This should also work for you.

FOO='one two three'
TWO='two'
if [[ "$FOO" =~ "$TWO"( |$) ]]
then
  echo "two is in the list"
else
    echo "two is not in the list"
fi

This will give an exact pattern match.

Hammed
  • 1,457
  • 1
  • 24
  • 37