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
How do I check if a variable exists in a list in BASH
提问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 list
is treated as an array and not a string,
all the string manipulations will validate 1
while 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 -w
checks 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 $x
is allowed.
然后用于validate "$x"
测试是否$x
允许。
If you want a one-liner, and don't care about whitespace in item names, you can use this (notice -w
instead of -x
):
如果你想要一个单行,并且不关心项目名称中的空格,你可以使用这个(注意-w
而不是-x
):
validate() { echo "11 22 33" | grep -F -q -w ""; }
Notes:
笔记:
- This is POSIX
sh
compliant. validate
does notaccept substrings (remove the-x
option to grep if you want that).validate
interprets its argument as a fixed string, not a regular expression (remove the-F
option 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 $VALUE
as 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无耻地窃取的)