Retornando um valor de uma função bash

10

Eu tenho uma função que retorna 1 se o número for um número de dez dígitos válido:

valNum()
{
    flag=1
    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=0
    fi
    return $flag
}

Está sendo chamado por:

if [[ $(valNum $num) -eq 1 ]]; then
      #do something
fi

A função está funcionando bem se o número for válido, mas estiver mostrando erro de sintaxe se inserir um número inválido.

    
por user2179293 15.09.2013 / 09:07

4 respostas

14

@ a resposta da choroba está correta, no entanto, este exemplo pode ser mais claro:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

Este exemplo é um pouco mais longo (definindo $valNumResult , em seguida, consultando esse valor), mas descreve mais explicitamente o que acontece: que valNum() retorna um valor e esse valor pode ser consultado e testado.

P.S. Por favor, faça um favor e retorne 0 para true e diferente de zero para false . Dessa forma, você pode usar o valor de retorno para indicar "por que falhamos" no caso de falha.

    
por 15.09.2013 / 11:27
8

As funções no bash só podem retornar códigos de saída. A substituição de comando, por outro lado, é usada para obter a saída padrão de um comando ou função. Portanto, para verificar o sinalizador retornado, você não precisa da substituição:

if valNum "$num" ; then
    # ...
fi

Mas, para que funcione, você deve retornar 0 se o número for válido e 1 se não for (o código de saída 0 significa que não há erro).

    
por 15.09.2013 / 09:16
5

Você não pode retornar um resultado arbitrário de uma função do shell. Você só pode retornar um código de status que seja um inteiro entre 0 e 255. (Embora você possa passar um valor maior para return , ele será truncado no módulo 256.) O valor deve ser 0 para indicar sucesso e um valor diferente para indicar falha; por convenção, você deve manter os códigos de erro entre 1 e 125, pois valores mais altos têm um significado especial (comando externo ruim para 126 e 127, morto por um sinal para valores mais altos).

Como você está retornando um resultado sim ou não aqui, um código de status é apropriado. Como flag parece indicar um sucesso ou uma falha, você deve usar os valores convencionais de 0 para sucesso e 1 para falha (o oposto do que você escreveu). Você pode então usar sua função diretamente em uma declaração if.

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

Se você precisar discriminar entre os códigos de falha, chame a função diretamente. Imediatamente após o retorno, o código de falha está disponível em $? . Você pode verificar isso com uma declaração de caso:

valNum "$num"
case $? in …

Se você precisar usar o código de status mais tarde, salve-o em outra variável antes que $? seja sobrescrito pelo próximo comando.

valNum "$num"
valNum_status=$?

O que você escreveu não funcionou porque a substituição de comando $(…) se expande para a saída da função, que em seu código é a mensagem de erro ou vazia, nunca 1 .

Se você precisar passar mais informações do que um código de status permite em algumas funções do shell, você tem duas possibilidades:

  • Imprime algum texto na saída padrão e chama a função em uma substituição de comando: $(valNum "$num")
  • Atribua uma ou mais variáveis dentro da função e leia essas variáveis mais tarde.
por 17.09.2013 / 01:52
2

Eu mesmo tive resultados conflitantes nessa área. Aqui estão os resultados de meus experimentos empíricos. Em primeiro lugar, algumas ' teoria ' sobre os comandos bash ou * nix:

  • SUCESSO == 0 ... viz. nenhum código de status de erro)
  • FAIL! = 0 ...... algum código de status

Exemplo:

if  ls -lt /nonexistantdir
then 
    echo "found"
else
    echo "FAIL"
fi
#
echo
ls -lt /nonexistantdir; echo "status = $?"
echo "status = $?"

Saída:

ls: cannot access '/nonexistantdir': No such file or directory
FAIL... 

ls: cannot access '/nonexistantdir': No such file or directory
status = 2

Como mostrado, o comando ls retorna o código de status = 2. Quando você tenta um diretório válido, o status é zero ( 0 ). Não é o mesmo que quase todas as outras línguas.

regra # 1 - Faça ...

  • TRUE == 0
  • FALSO! = 0

Devemos lembrar que estamos testando códigos de erro em uma instrução Bash if . Eu configuro constantes, ou você pode usar os comandos shell true ou false .

TRUE=0
FALSE=1

#  valid number function
#
valNum()
{
    flag=$TRUE

    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=$FALSE
    fi
    return $flag
}

#    later on ...
#
if validNum Abc 
then
    echo "Lucky number"
else
    echo "Not lucky."
fi

e saída:

Invalid Number
Not lucky.

No entanto, sugiro que você dê qualquer ' up-vote ' @Gilles porque a resposta dele é a correta. Eu só queria deixar o lado simplista no ePaper.

Apenas mais uma coisa, o comando test . Isso parece:

[[ some-expression ]]; 

Na maioria das vezes. E por exemplo:

$ test 1
$ echo "result = $?"
result = 0
$ test 0
$ echo "result = $?"
result = 0

Zero (0) sendo true . Por quê? Bem, a página man diz que um único argumento é ' verdadeiro ' quando é NOT-NULL.

Referências

:

por 28.02.2017 / 14:45