Shell:在 if 中使用带参数的函数

Shell:在 if 中使用带参数的函数

我正在尝试执行下面的代码,但是当我尝试在 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
  • -aoption 既不是 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

我认为这更简单,但缺乏许多人喜欢的 && 逻辑。

相关内容