Linux 如何检查变量是否存在于 BASH 的列表中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8063228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 07:07:05  来源:igfitidea点击:

How do I check if a variable exists in a list in BASH

linuxbash

提问by Ofir Farchy

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.

我正在尝试用 bash 编写一个脚本来检查用户输入的有效性。
我想将输入(比如变量x)与有效值列表相匹配。

what I have come up with at the moment is:

我现在想出的是:

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

My question is if there is a simpler way to do this,
something like a list.contains(x)for most programming languages.

我的问题是是否有一种更简单的方法可以做到这一点,
就像list.contains(x)大多数编程语言的a 一样。

Addition:
Say list is:

补充:
说列表是:

list="11 22 33"

my code will echo the message only for those values since listis treated as an array and not a string, all the string manipulations will validate 1while I would want it to fail.

我的代码将只为这些值回显消息,因为list被视为数组而不是字符串,所有字符串操作都将验证,1而我希望它失败。

采纳答案by chemila

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

or create a function:

或创建一个函数:

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

to use it:

使用它:

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

回答by Kent

how about

怎么样

echo $list | grep -w $x

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

您可以检查输出或 $?以上行来做出决定。

grep -wchecks on whole word patterns.

grep -w检查整个单词模式。

回答by Mithun Sasidharan

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

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

string='My string';

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

回答by Oriettaxx

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

Matvey 是对的,但您应该引用 $x 并考虑使用任何类型的“空格”(例如换行)

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

so, i.e.

所以,即

# list_include_item "10 11 12" "2"
function list_include_item {
  local list=""
  local item=""
  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"

回答by RubyTuesdayDONO

Consider exploiting the keys of associative arrays. I would presume this outperforms both regex/pattern matching and looping, although I haven't profiled it.

考虑利用关联数组的键。我认为这优于正则表达式/模式匹配和循环,尽管我没有对其进行分析。

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

Output:

输出:

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 )
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 )

回答by S?ren L?vborg

If the list is fixed in the script, I like the following the best:

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

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

Then use validate "$x"to test if $xis allowed.

然后用于validate "$x"测试是否$x允许。

If you want a one-liner, and don't care about whitespace in item names, you can use this (notice -winstead of -x):

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

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

Notes:

笔记:

  • This is POSIX shcompliant.
  • validatedoes notaccept substrings (remove the -xoption to grep if you want that).
  • validateinterprets its argument as a fixed string, not a regular expression (remove the -Foption to grep if you want that).
  • 这是sh符合POSIX 的。
  • validate没有接受子(去除-x,如果你想要那个选项的grep)。
  • validate将其参数解释为固定字符串,而不是正则表达式(-F如果需要,请删除grep 选项)。

Sample code to exercise the function:

执行该功能的示例代码:

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

回答by Brad Parks

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  OPTION1 OPTION2) == "NO" ]
then
  echo "UNKNOWN type for param 1: Should be OPTION1 or OPTION2"
  exit;
fi

in_list

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 [ "" == "help" ]
then
  show_help
fi

if [ "$#" -eq 0 ]; then
  show_help
fi

SEARCH_FOR=
shift;

for ITEM in "$@"
do
  if [ "$SEARCH_FOR" == "$ITEM" ]
  then
    echo "YES"
    exit;
  fi
done

echo "NO"

回答by Toby Speight

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:

如果您的值列表要在脚本中进行硬编码,则使用case. 这是一个简短的示例,您可以根据自己的要求进行调整:

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.

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

回答by Sébastien Pierre

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

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

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.

请注意,"测试工作需要 。

回答by blaimi

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.

对于包含针作为子字符串的值的值,例如使用 haystack ,这不会是误报foo barbaz

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

(这个概念是从 JQuery 的hasClass()-Method无耻地窃取的)