我想知道是否有一种有效的方法来检查Bash数组中是否存在元素?我正在寻找类似于Python的功能:
arr = ['a','b','c','d']
if 'd' in arr:
do your thing
else:
do something
我已经看到了针对Bash 4+使用针对bash的关联数组的解决方案,但是我想知道是否还有其他解决方案。
请理解,我知道微不足道的解决方案是在数组中进行迭代,但是我不希望这样。
我想知道是否有一种有效的方法来检查Bash数组中是否存在元素?我正在寻找类似于Python的功能:
arr = ['a','b','c','d']
if 'd' in arr:
do your thing
else:
do something
我已经看到了针对Bash 4+使用针对bash的关联数组的解决方案,但是我想知道是否还有其他解决方案。
请理解,我知道微不足道的解决方案是在数组中进行迭代,但是我不希望这样。
Answers:
您可以这样做:
if [[ " ${arr[*]} " == *" d "* ]]; then
echo "arr contains d"
fi
例如,如果您查找“ a b”,这将产生误报-该子字符串在连接的字符串中,但不作为数组元素。无论您选择哪种定界符,都会出现此难题。
最安全的方法是遍历数组直到找到元素:
array_contains () {
local seeking=$1; shift
local in=1
for element; do
if [[ $element == "$seeking" ]]; then
in=0
break
fi
done
return $in
}
arr=(a b c "d e" f g)
array_contains "a b" "${arr[@]}" && echo yes || echo no # no
array_contains "d e" "${arr[@]}" && echo yes || echo no # yes
这是一个“更干净”的版本,您只需传递数组名称,而不是传递其所有元素
array_contains2 () {
local array="$1[@]"
local seeking=$2
local in=1
for element in "${!array}"; do
if [[ $element == "$seeking" ]]; then
in=0
break
fi
done
return $in
}
array_contains2 arr "a b" && echo yes || echo no # no
array_contains2 arr "d e" && echo yes || echo no # yes
对于关联数组,有测试一个非常整洁的方式,如果该数组包含一个给定的关键:在-v
运营商
$ declare -A arr=( [foo]=bar [baz]=qux )
$ [[ -v arr[foo] ]] && echo yes || echo no
yes
$ [[ -v arr[bar] ]] && echo yes || echo no
no
请参见手册中的6.4 Bash条件表达式。
$seeking
以免将其视为模式。
除了明显的警告外,如果您的阵列实际上像上面的阵列,则可以
if [[ ${arr[*]} =~ d ]]
then
do your thing
else
do something
fi
d
也会匹配xdy
。
if [[ ${arr[*]} =~ $(echo '\<d\>') ]]
(来源)
1)初始化数组arr
并添加元素
2)设置要搜索的变量 SEARCH_STRING
3)检查您的数组是否包含元素
arr=()
arr+=('a')
arr+=('b')
arr+=('c')
SEARCH_STRING='b'
if [[ " ${arr[*]} " == *"$SEARCH_STRING"* ]];
then
echo "YES, your arr contains $SEARCH_STRING"
else
echo "NO, your arr does not contain $SEARCH_STRING"
fi
BASH_ARGV
来测试是否给出了某个单词作为参数,而该参数要求使用一次性的不同设置,而不必argparse
为这种情况做过多的设置。
如果数组元素不包含空格,则另一个解决方案(也许更易读)将是:
if echo ${arr[@]} | grep -q -w "d"; then
echo "is in array"
else
echo "is not in array"
fi
--
以表示参数的结尾,负数将不会被视为grep的参数
array=("word" "two words") # let's look for "two words"
grep
和printf
:(printf '%s\n' "${array[@]}" | grep -x -q "two words") && <run_your_if_found_command_here>
for
:(for e in "${array[@]}"; do [[ "$e" == "two words" ]] && exit 0; done; exit 1) && <run_your_if_found_command_here>
对于not_found结果,请添加 || <run_your_if_notfound_command_here>
grep -x...
使它最容易使用。
由于bash没有内置的值 in
数组运算符,并且该=~
运算符或[[ "${array[@]" == *"${item}"* ]]
符号使我感到困惑,因此我通常将其grep
与here-string结合使用:
colors=('black' 'blue' 'light green')
if grep -q 'black' <<< "${colors[@]}"
then
echo 'match'
fi
但是请注意,与完全包含要搜索的项目但不等于另一个项目时发生的许多其他答案一样,它也会遭受相同的误报问题:
if grep -q 'green' <<< "${colors[@]}"
then
echo 'should not match, but does'
fi
如果这是用例的问题,则可能无法遍历数组:
for color in "${colors[@]}"
do
if [ "${color}" = 'green' ]
then
echo "should not match and won't"
break
fi
done
for color in "${colors[@]}"
do
if [ "${color}" = 'light green' ]
then
echo 'match'
break
fi
done
-x
到grep中以匹配整行。
就计算时间而言,这是另一种比迭代更快的方法。不确定。这个想法是将数组转换为字符串,截断它,并获取新数组的大小。
例如,要查找索引“ d”:
arr=(a b c d)
temp=`echo ${arr[@]}`
temp=( ${temp%%d*} )
index=${#temp[@]}
您可以将其转换为类似以下的功能:
get-index() {
Item=$1
Array="$2[@]"
ArgArray=( ${!Array} )
NewArray=( ${!Array%%${Item}*} )
Index=${#NewArray[@]}
[[ ${#ArgArray[@]} == ${#NewArray[@]} ]] && echo -1 || echo $Index
}
然后,您可以致电:
get-index d arr
它将回显3,可以分配给:
index=`get-index d arr`
bash
可以通过简单的数组来完成所需的操作。