Check if a variable exists in a list in Bash

后端 未结 17 465
囚心锁ツ
囚心锁ツ 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:44

    Assuming TARGET variable can be only 'binomial' or 'regression', then following would do:

    # Check for modeling types known to this script
    if [ $( echo "${TARGET}" | egrep -c "^(binomial|regression)$" ) -eq 0 ]; then
        echo "This scoring program can only handle 'binomial' and 'regression' methods now." >&2
        usage
    fi
    

    You could add more strings into the list by separating them with a | (pipe) character.

    Advantage of using egrep, is that you could easily add case insensitivity (-i), or check more complex scenarios with a regular expression.

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

    This is almost your original proposal but almost a 1-liner. Not that complicated as other valid answers, and not so depending on bash versions (can work with old bashes).

    OK=0 ; MP_FLAVOURS="vanilla lemon hazelnut straciatella"
    for FLAV in $MP_FLAVOURS ; do [ $FLAV == $FLAVOR ] && { OK=1 ; break; } ; done
    [ $OK -eq 0 ] && { echo "$FLAVOR not a valid value ($MP_FLAVOURS)" ; exit 1 ; }
    

    I guess my proposal can still be improved, both in length and style.

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

    how about

    echo $list | grep -w -q $x
    

    you could either check the output or $? of above line to make the decision.

    grep -w checks on whole word patterns. Adding -q prevents echoing the list.

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

    Matvey is right, but you should quote $x and consider any kind of "spaces" (e.g. new line) with

    [[ $list =~ (^|[[:space:]])"$x"($|[[:space:]]) ]] && echo 'yes' || echo 'no' 
    

    so, i.e.

    # list_include_item "10 11 12" "2"
    function list_include_item {
      local list="$1"
      local item="$2"
      if [[ $list =~ (^|[[:space:]])"$item"($|[[:space:]]) ]] ; then
        # yes, list include item
        result=0
      else
        result=1
      fi
      return $result
    }
    

    end then

    `list_include_item "10 11 12" "12"`  && echo "yes" || echo "no"
    

    or

    if `list_include_item "10 11 12" "1"` ; then
      echo "yes"
    else 
      echo "no"
    fi
    

    Note that you must use "" in case of variables:

    `list_include_item "$my_list" "$my_item"`  && echo "yes" || echo "no"
    
    0 讨论(0)
  • 2020-11-29 17:48

    The shell built-in compgen can help here. It can take a list with the -W flag and return any of the potential matches it finds.

    # My list can contain spaces so I want to set the internal
    # file separator to newline to preserve the original strings.
    IFS=$'\n'
    
    # Create a list of acceptable strings.
    accept=( 'foo' 'bar' 'foo bar' )
    
    # The string we will check
    word='foo'
    
    # compgen will return a list of possible matches of the 
    # variable 'word' with the best match being first.
    compgen -W "${accept[*]}" "$word"
    
    # Returns:
    # foo
    # foo bar
    

    We can write a function to test if a string equals the best match of acceptable strings. This allows you to return a 0 or 1 for a pass or fail respectively.

    function validate {
      local IFS=$'\n'
      local accept=( 'foo' 'bar' 'foo bar' )
      if [ "$1" == "$(compgen -W "${accept[*]}" "$1" | head -1)" ] ; then
        return 0
      else
        return 1
      fi
    }
    

    Now you can write very clean tests to validate if a string is acceptable.

    validate "blah" || echo unacceptable
    
    if validate "foo" ; then
      echo acceptable
    else 
      echo unacceptable
    fi
    
    0 讨论(0)
  • 2020-11-29 17:51

    You can use (* wildcards) outside a case statement, too, if you use double brackets:

    string='My string';
    
    if [[ $string == *My* ]]
    then
    echo "It's there!";
    fi
    
    0 讨论(0)
提交回复
热议问题