Shell: Usando a função com parâmetros em if

8

Estou tentando executar o código abaixo, mas quando tento usar minha função na instrução if, recebo o erro -bash: [: too many arguments . Por que isso está acontecendo?

Obrigado antecipadamente!

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
    
por Andrea Silvestri 13.07.2018 / 16:20

3 respostas

14

Ao usar if [ ... ] você está realmente usando o utilitário [ (que é o mesmo que test , mas requer que o último argumento seja ] ).

[ não entende rodar sua função, ela espera strings. Felizmente, você não precisa usar [ aqui (pelo menos para a função):

if [ "$docheck" -eq 1 ] && notContainsElement "$fruit" "${blacklist[@]}"; then
  ...
fi

Note que eu também estou verificando o inteiro primeiro, para que possamos evitar chamar a função se $docheck não for 1.

Isso funciona porque if recebe um comando arbitrário e decide o que fazer no status de saída desse comando. Aqui, usamos um teste [ ... ] juntamente com uma chamada para sua função, com && intermediário, criando um comando composto. O status de saída do comando composto seria verdadeiro se o [ ... ] test e a função retornassem zero como seus status de saída, sinalizando sucesso.

Como nota de estilo, eu não teria a função testar se a matriz não contém o elemento, mas se contém o elemento e, em seguida,

if [ "$docheck" -eq 1 ] && ! contains "$fruit" "${blacklist[@]}"; then ...

Ter um teste de função um negativo vai atrapalhar a lógica nos casos em que você faz deseja testar se o array contém o elemento ( if ! notContainsElement ... ).

    
por 13.07.2018 / 16:25
3

tente

if notContainsElement "$fruit" "${blacklist[@]}" && test "$docheck" = 1
then
    A opção
  • -a não é um shell nem uma opção test

aqui você tem dois testes de parte

notContainsElement "$fruit" "${blacklist[@]}"
test $docheck = 1 ## or [ $docheck = 1 ]

você vincula em if usando

if cmd1 && cmd2

como apontado -a é uma opção de teste, mas só pode ser usada com outra opção de teste, assim você pode usar

if [ "$a" -lt "$b" -a "$a" -lt "$c" ]

para testar se $a é menor do que o $b e $c , mas você não pode usar outro comando no escopo do teste.

    
por 13.07.2018 / 16:26
0

Aqui está uma alternativa que algumas pessoas podem não gostar. Converta sua matriz de lista negra em uma string e veja se a string com uma fruta removida é a mesma. Editado para preencher as cordas com espaços. Obrigado a Scott por apontar o problema da maçã / abacaxi.

badlist=" ${blacklist[@]} "
for f in "${list[@]}"
do
    if [[ "${badlist/" $f "/}" == "$badlist" ]]
    then
        echo "$f"
    fi
done

Acho que isso é mais simples, mas falta o & & lógica que muitos preferem.

    
por 13.07.2018 / 19:51