Answers:
在Bash 4中,您可以使用关联数组:
# set up array of constants
declare -A array
for constant in foo bar baz
do
array[$constant]=1
done
# test for existence
test1="bar"
test2="xyzzy"
if [[ ${array[$test1]} ]]; then echo "Exists"; fi # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi # doesn't
要最初设置阵列,您还可以直接分配:
array[foo]=1
array[bar]=1
# etc.
或者这样:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
很简单,但有一个问题:如果set -u
在脚本中使用(建议使用),它将不起作用,因为您会得到“未绑定变量”。
这是一个老问题,但是我认为最简单的解决方案尚未出现:test ${array[key]+_}
。例:
declare -A xs=([a]=1 [b]="")
test ${xs[a]+_} && echo "a is set"
test ${xs[b]+_} && echo "b is set"
test ${xs[c]+_} && echo "c is set"
输出:
a is set
b is set
要查看此工作方式,请检查此内容。
env
以避免别名,程序和其他可能采用名称“ test”的函数出现歧义。如上env test ${xs[a]+_} && echo "a is set"
。您也可以使用双括号来获得此功能,然后使用相同的技巧然后检查是否为空:[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
有一种方法可以测试关联数组的元素是否存在(未设置),这不同于空:
isNotSet() {
if [[ ! ${!1} && ${!1-_} ]]
then
return 1
fi
}
然后使用它:
declare -A assoc
KEY="key"
isNotSet assoc[${KEY}]
if [ $? -ne 0 ]
then
echo "${KEY} is not set."
fi
if ! some_check then return 1
= some_check
。因此:isNotSet() { [[ ... ]] }
。请在下面检查我的解决方案,只需简单检查即可。
您可以通过将数组的内容传递给grep来查看是否存在条目。
printf "%s\n" "${mydata[@]}" | grep "^${val}$"
您还可以使用grep -n获取条目的索引,该索引返回匹配项的行号(请记住减去1以获取从零开始的索引)。除了非常大的数组之外,这将相当快。
# given the following data
mydata=(a b c "hello world")
for val in a c hello "hello world"
do
# get line # of 1st matching entry
ix=$( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 )
if [[ -z $ix ]]
then
echo $val missing
else
# subtract 1. Bash arrays are zero-based, but grep -n returns 1 for 1st line, not 0
echo $val found at $(( ix-1 ))
fi
done
a found at 0
c found at 2
hello missing
hello world found at 3
说明:
$( ... )
与使用反引号将命令的输出捕获到变量中相同 printf
输出mydata每行一个元素 @
相反的是,*.
避免将“ hello world”分成两行)grep
搜索确切的字符串: ^
并$
匹配行的开头和结尾grep -n
以4:hello world的形式返回行号 grep -m 1
仅找到第一个比赛cut
仅提取行号 您当然可以将减法折叠到命令中。但是然后测试-1是否丢失:
ix=$(( $( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 ) - 1 ))
if [[ $ix == -1 ]]; then echo missing; else ... fi
$(( ... ))
做整数算术我认为除非循环中的数据非常有限,否则您无法在没有循环的情况下正确地进行操作。
这是一个简单的变体,可以正确地说它"Super User"
存在于数组中。但是它也可以说"uper Use"
在数组中。
MyArray=('Super User' 'Stack Overflow' 'Server Fault' 'Jeff' );
FINDME="Super User"
FOUND=`echo ${MyArray[*]} | grep "$FINDME"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
#
# If you where to add anchors < and > to the data it could work
# This would find "Super User" but not "uper Use"
#
MyArray2=('<Super User>' '<Stack Overflow>' '<Server Fault>' '<Jeff>' );
FOUND=`echo ${MyArray2[*]} | grep "<$FINDME>"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
问题在于,除了循环遍历数组之外,没有简单的方法可以添加锚(我能想到的)。除非您可以在将它们放入数组之前添加它们...
grep "\b$FINDME\b"
。可能可以与没有空格的非字母数字常量一起使用"(^| )$FINDME(\$| )"
(或类似的东西……我从来无法了解正则表达式grep使用的是什么味道。)
#!/bin/bash
function in_array {
ARRAY=$2
for e in ${ARRAY[*]}
do
if [[ "$e" == "$1" ]]
then
return 0
fi
done
return 1
}
my_array=(Drupal Wordpress Joomla)
if in_array "Drupal" "${my_array[*]}"
then
echo "Found"
else
echo "Not found"
fi
in_array
。干杯
${ARRAY[@]}
应该使用。