如何检查一个variables是否存在于BASH的列表中

我正在尝试在bash中编写一个脚本来检查用户input的有效性。
我想匹配input(比如variablesx )到一个有效值列表。

我现在提出的是:

 for item in $list do if [ "$x" == "$item" ]; then echo "In the list" exit fi done 

我的问题是如果有一个更简单的方法来做到这一点,
就像大多数编程语言的list.contains(x)一样。

加成:
说清单是:

 list="11 22 33" 

我的代码将回显消息只为这些值,因为list被视为一个数组而不是一个string,所有的string操作将validation1而我希望它失败。

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

或者创build一个函数:

 contains() { [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && exit(0) || exit(1) } 

使用它:

 contains aList anItem echo $? # 0: match, 1: failed 

马特是正确的,但你应该引用$ x并考虑任何types的“空格”(如新行)

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

所以,即

 # 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 } 

结束然后

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

要么

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

请注意,您必须在variables的情况下使用""

 `list_include_item "$my_list" "$my_item"` && echo "yes" || echo "no" 

如果使用双括号,则也可以在case语句外使用(*通配符):

 string='My string'; if [[ $string == *My* ]] then echo "It's there!"; fi 

怎么样

 echo $list|grep $x 

你可以检查输出或$? 作出决定。

考虑利用关联数组的键。 我会认为这胜过正则expression式/模式匹配和循环,虽然我没有分析它。

 declare -A list=( [one]=1 [two]=two [three]='any non-empty value' ) for value in one two three four do echo -n "$value is " # a missing key expands to the null string, # and we've set each interesting key to a non-empty value [[ -z "${list[$value]}" ]] && echo -n '*not* ' echo "a member of ( ${!list[*]} )" done 

输出:

 one is a member of ( one two three ) two is a member of ( one two three ) three is a member of ( one two three ) four is *not* a member of ( one two three ) 

我发现使用echo $LIST | xargs -n1 echo | grep $VALUE更容易 echo $LIST | xargs -n1 echo | grep $VALUE echo $LIST | xargs -n1 echo | grep $VALUE如下图所示:

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

这适用于以空格分隔的列表,但可以通过执行以下操作将其适用于任何其他分隔符(如:):

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

请注意, "是testing工作所必需的。

如果列表在脚本中是固定的,我喜欢以下最好的:

 validate() { grep -F -q -x "$1" <<EOF item 1 item 2 item 3 EOF } 

然后使用validate "$x"来testing是否允许$x

如果你想要一个单行,而不关心项目名称中的空格,你可以使用这个(注意-w而不是-x ):

 validate() { echo "11 22 33" | grep -F -q -w "$1"; } 

笔记:

  • 这是POSIX sh兼容。
  • validate不接受子string(如果需要的话,删除-x选项以grep)。
  • validate将它的参数解释为一个固定的string,而不是一个正则expression式(如果你想要的话,删除-F选项来grep)。

示例代码来锻炼function:

 for x in "item 1" "item2" "item 3" "3" "*"; do echo -n "'$x' is " validate "$x" && echo "valid" || echo "invalid" done 

如果您的值列表要在脚本中进行硬编码,则使用case进行testing非常简单。 这里有一个简短的例子,你可以适应你的要求:

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

如果列表在运行时是一个数组variables,其他答案之一可能更适合。

恕我直言,最简单的解决scheme是prepend和追加原始string与空格,并与[[ ]]检查正则expression式

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

这个值不会是假的,值包含针头作为子string,例如干草堆foo barbaz

(这个概念被无耻地从JQuery的hasClass()方法中窃取)

例子

 $ 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} ... eg abcd -> NO abad -> 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"