Check if a variable exists in a list in Bash

后端 未结 17 464
囚心锁ツ
囚心锁ツ 2020-11-29 17:08

I am trying to write a script in bash that check the validity of a user input.
I want to match the input (say variable x) to a list of valid values.

<
相关标签:
17条回答
  • 2020-11-29 17:33

    If your list of values is to be hard-coded in the script, it's fairly simple to test using case. Here's a short example, which you can adapt to your requirements:

    for item in $list
    do
        case "$x" in
          item1|item2)
            echo "In the list"
            ;;
          not_an_item)
            echo "Error" >&2
            exit 1
            ;;
        esac
    done
    

    If the list is an array variable at runtime, one of the other answers is probably a better fit.

    0 讨论(0)
  • 2020-11-29 17:35

    Examples

    $ in_list super test me out
    NO
    
    $ in_list "super dude" test me out
    NO
    
    $ in_list "super dude" test me "super dude"
    YES
    
    # How to use in another script
    if [ $(in_list $1 OPTION1 OPTION2) == "NO" ]
    then
      echo "UNKNOWN type for param 1: Should be OPTION1 or OPTION2"
      exit;
    fi
    

    in_list

    function show_help()
    {
      IT=$(CAT <<EOF
    
      usage: SEARCH_FOR {ITEM1} {ITEM2} {ITEM3} ...
    
      e.g. 
    
      a b c d                    -> NO
      a b a d                    -> YES
      "test me" how "test me"    -> YES
    
      )
      echo "$IT"
      exit
    }
    
    if [ "$1" == "help" ]
    then
      show_help
    fi
    
    if [ "$#" -eq 0 ]; then
      show_help
    fi
    
    SEARCH_FOR=$1
    shift;
    
    for ITEM in "$@"
    do
      if [ "$SEARCH_FOR" == "$ITEM" ]
      then
        echo "YES"
        exit;
      fi
    done
    
    echo "NO"
    
    0 讨论(0)
  • 2020-11-29 17:36

    If it isn't too long; you can just string them between equality along a logical OR comparison like so.

    if [ $ITEM == "item1" -o $ITEM == "item2" -o $ITEM == "item3" ]; then
        echo In the list
    fi 
    

    I had this exact problem and while the above is ugly it is more obvious what is going on than the other generalized solutions.

    0 讨论(0)
  • 2020-11-29 17:38

    IMHO easiest solution is to prepend and append the original string with a space and check against a regex with [[ ]]

    haystack='foo bar'
    needle='bar'
    
    if [[ " $haystack " =~ .*\ $needle\ .* ]]; then
        ...
    fi
    

    this will not be false positive on values with values containing the needle as a substring, e.g. with a haystack foo barbaz.

    (The concept is shamelessly stolen form JQuery's hasClass()-Method)

    0 讨论(0)
  • 2020-11-29 17:39

    I find it's easier to use the form echo $LIST | xargs -n1 echo | grep $VALUE as illustrated below:

    LIST="ITEM1 ITEM2"
    VALUE="ITEM1"
    if [ -n "`echo $LIST | xargs -n1 echo | grep -e \"^$VALUE`$\" ]; then
        ...
    fi
    

    This works for a space-separated list, but you could adapt it to any other delimiter (like :) by doing the following:

    LIST="ITEM1:ITEM2"
    VALUE="ITEM1"
    if [ -n "`echo $LIST | sed 's|:|\\n|g' | grep -e \"^$VALUE`$\"`" ]; then
       ...
    fi
    

    Note that the " are required for the test to work.

    0 讨论(0)
  • 2020-11-29 17:42

    Thought I'd add my solution to the list.

    # Checks if element "$1" is in array "$2"
    # @NOTE:
    #   Be sure that array is passed in the form:
    #       "${ARR[@]}"
    elementIn () {
        # shopt -s nocasematch # Can be useful to disable case-matching
        local e
        for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
        return 1
    }
    
    # Usage:
    list=(11 22 33)
    item=22
    
    if elementIn "$item" "${list[@]}"; then
        echo TRUE;
    else
        echo FALSE
    fi
    # TRUE
    
    item=44
    elementIn $item "${list[@]}" && echo TRUE || echo FALSE
    # FALSE
    
    0 讨论(0)
提交回复
热议问题