How can I compare a string to multiple correct values in Bash?

StringBashComparisonCompare

String Problem Overview


I have the following piece of Bash script:

function get_cms {
    echo "input cms name"
    read cms
    cms=${cms,,}
    if [ "$cms" != "wordpress" && "$cms" != "meganto" && "$cms" != "typo3" ]; then
        get_cms
    fi
}

But no matter what I input (correct and incorrect values), it never calls the function again, because I only want to allow 1 of those 3 inputs.

I have tried it with ||, with [ var != value ] or [ var != value1 ] or [ var != value1 ], but nothing works.

Can someone point me in the right direction?

String Solutions


Solution 1 - String

If the main intent is to check whether the supplied value is not found in a list, maybe you can use the extended regular expression matching built in BASH via the "equal tilde" operator (see also this answer):

if ! [[ "$cms" =~ ^(wordpress|meganto|typo3)$ ]]; then get_cms ; fi

Solution 2 - String

Instead of saying:

if [ "$cms" != "wordpress" && "$cms" != "meganto" && "$cms" != "typo3" ]; then

say:

if [[ "$cms" != "wordpress" && "$cms" != "meganto" && "$cms" != "typo3" ]]; then

You might also want to refer to Conditional Constructs.

Solution 3 - String

Maybe you should better use a case for such lists:

case "$cms" in
  wordpress|meganto|typo3)
    do_your_else_case
    ;;
  *)
    do_your_then_case
    ;;
esac

I think for long such lists this is better readable.

If you still prefer the if you can do it with single brackets in two ways:

if [ "$cms" != wordpress -a "$cms" != meganto -a "$cms" != typo3 ]; then

or

if [ "$cms" != wordpress ] && [ "$cms" != meganto ] && [ "$cms" != typo3 ]; then

Solution 4 - String

As @Renich suggests (but with an important typo that has not been fixed unfortunately), you can also use extended globbing for pattern matching. So you can use the same patterns you use to match files in command arguments (e.g. ls *.pdf) inside of bash comparisons.

For your particular case you can do the following.

if [[ "${cms}" != @(wordpress|magento|typo3) ]]

The @ means "Matches one of the given patterns". So this is basically saying cms is not equal to 'wordpress' OR 'magento' OR 'typo3'. In normal regular expression syntax @ is similar to just ^(wordpress|magento|typo3)$.

Mitch Frazier has two good articles in the Linux Journal on this Pattern Matching In Bash and Bash Extended Globbing.

For more background on extended globbing see Pattern Matching (Bash Reference Manual).

Solution 5 - String

Here's my solution

if [[ "${cms}" != @(wordpress|magento|typo3) ]]; then

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioneagle00789View Question on Stackoverflow
Solution 1 - StringEdgar GrillView Answer on Stackoverflow
Solution 2 - StringdevnullView Answer on Stackoverflow
Solution 3 - StringAlfeView Answer on Stackoverflow
Solution 4 - StringstudgeekView Answer on Stackoverflow
Solution 5 - StringRenichView Answer on Stackoverflow