我正在尝试执行下面的代码,但是当我尝试在 if 语句中使用我的函数时,出现错误-bash: [: too many arguments
。为什么会发生这种情况?
先感谢您!
notContainsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 1; done
return 0
}
list=( "pears" "apples" "bananas" "oranges" )
blacklist=( "oranges" "apples" )
docheck=1
for fruit in "${list[@]}"
do
if [ notContainsElement "$fruit" "${blacklist[@]}" -a $docheck = 1 ]
then
echo $fruit
fi
done
答案1
使用时,if [ ... ]
您实际上正在使用该[
实用程序(与 相同,test
但要求最后一个参数是]
)。
[
不明白运行你的函数,它需要字符串。幸运的是,您根本不需要[
在这里使用(至少对于该功能):
if [ "$docheck" -eq 1 ] && notContainsElement "$fruit" "${blacklist[@]}"; then
...
fi
请注意,我还首先检查整数,这样我们就可以避免在$docheck
不为 1 时调用该函数。
这是有效的,因为if
接受任意命令并根据该命令的退出状态决定要执行的操作。在这里,我们使用[ ... ]
测试和对函数的调用,并&&
在中间创建一个复合命令。如果[ ... ]
测试和函数都返回零作为退出状态,则复合命令的退出状态将为 true ,表示成功。
作为风格注释,我不会让函数测试数组是否不是包含该元素但是否 if做包含该元素,然后
if [ "$docheck" -eq 1 ] && ! contains "$fruit" "${blacklist[@]}"; then ...
如果您的功能测试结果为负,则会扰乱逻辑做想要测试数组是否包含元素 ( if ! notContainsElement ...
)。
答案2
尝试
if notContainsElement "$fruit" "${blacklist[@]}" && test "$docheck" = 1
then
-a
option 既不是 shell 也不是test
选项
这里有两部分测试
notContainsElement "$fruit" "${blacklist[@]}"
test $docheck = 1 ## or [ $docheck = 1 ]
然后你链接if
使用
if cmd1 && cmd2
正如所指出的,-a
这是一个测试选项,但只能与其他测试选项一起使用,因此您可以使用
if [ "$a" -lt "$b" -a "$a" -lt "$c" ]
测试$a
低于 和 的值$b
,$c
但不能在测试范围内使用其他命令。
答案3
这是一些人可能不喜欢的替代方案。将你的黑名单数组转换为字符串,看看去掉水果的字符串是否相同。编辑以用空格填充字符串。感谢斯科特指出苹果/菠萝问题。
badlist=" ${blacklist[@]} "
for f in "${list[@]}"
do
if [[ "${badlist/" $f "/}" == "$badlist" ]]
then
echo "$f"
fi
done
我认为这更简单,但缺乏许多人喜欢的 && 逻辑。