Atribuindo código de saída a uma variável local do shell

28
#!/bin/bash
function0()
{
 local t1=$(exit 1)
 echo $t1
}

function0

echo imprime o valor vazio. Eu esperava:

1

Por que a variável t1 não é atribuída ao valor de retorno do comando de saída - 1 ?

    
por Madhavan Kumar 06.06.2015 / 17:06

4 respostas

44

local t1=$(exit 1) diz ao shell para:

  • execute exit 1 em uma subshell;
  • armazena sua saída (como no texto que sai para a saída padrão) em uma variável t1 , local para a função.

Assim, é normal que t1 acabe sendo vazio.

( $() é conhecido como substituição de comando .)

O código de saída é sempre atribuído a $? , então você pode fazer

function0()
{
  (exit 1)
  echo "$?"
}

para obter o efeito que você está procurando. Você pode, obviamente, atribuir $? a outra variável:

function0()
{
  (exit 1)
  local t1=$?
  echo "$t1"
}
    
por 06.06.2015 / 17:13
9

O código de saída foi armazenado na variável $? . Ao usar a Substituição de Comando , apenas capture a saída, você deve usar (...) para criar subshell :

#!/bin/bash

func() {
  (exit 1)
  local t1=$?
  printf '%d\n' "$t1"
}

func
    
por 06.06.2015 / 17:14
7

Em bash , isso funciona:

loc(){  local   "x=$(exit "$1"):$?"
        printf  '$%s:\t%d\n' \
                 x "${x##*:}" \? "$?"
}

Tem a ver com a ordem de avaliação de comando e atribuição de variável. local tem um valor de retorno próprio - e é o comando atualmente em execução, não a substituição de comando. A razão pela qual as coisas gostam ...

x=$(exit 1); echo "$?"

... pode retornar 1 porque nunca há um retorno nesse comando, a não ser que a subshell execute para atribuir o valor de $x - portanto, $? não é afetado, como acontece em praticamente todos os outros casos em que as substituições de comando são usadas.

De qualquer forma, com local é espancado - mas se você o captar na hora certa - que é enquanto as expansões ainda estão sendo avaliadas e antes As rotinas de local têm a chance de derrotá-lo - você ainda pode atribuí-lo.

unset x; loc 130; echo "${x-\$x is unset}"

... imprime ...

$x: 130
$?: 0
$x is unset

Você deve saber que em muitos shells você não pode confiar em $? sendo definido como mid-evaluation dessa maneira. Na verdade, isso é provavelmente porque essas shells não se incomodam em reavaliar em todas as ocasiões possíveis, como talvez bash faça - o que eu diria é provavelmente um comportamento melhor do que bash . Você realmente quer que o seu interpretador recursivamente valorize os valores de avaliação que provavelmente serão sobrescritos antes de você ter a chance de usá-los?

De qualquer forma, é assim que você pode fazer isso.

    
por 07.06.2015 / 17:00
-1

Dependendo do motivo pelo qual você está tentando apenas obter o código de saída, também é possível executar if some-command; then echo "Success $?"; else echo "Failure $?"; fi , que não faz nada com a saída do comando, apenas avalia o código de saída do comando executado. Você pode adicionar or ( or $ ( around the command and you'll still get the same results. A better example might be se grep -q 'somestring' somefile; em seguida, echo "O código de saída encontrado é $?"; Else "Não foi encontrado o código de saída menor é $?"; Fi '.

Você também pode testar o código de retorno de uma função que pode ser um return 3 explícito ou um código de retorno implícito que é o resultado do último comando, nesse caso você precisa ter cuidado para não ter um echo no final da função, caso contrário, ele irá mascarar / redefinir o código de saída anterior.

command_last () {
  echo "True is 'true'"
  echo "False is 'false'"
  false
}
command_last; echo $?
# Outputs:
# True is 0
# False is 1
# 1

echo_last () {
  echo "True is 'true'"
  echo "False is 'false'"
  false
  # echo'ing literally anything (or nothing) returns true aka exit 0
  echo
}
echo_last; echo $?
# Outputs:
# True is 0
# False is 1
#            # Blank line due to empty echo
# 0

Finalmente, um truque sujo, já que você não pode fazer VAR=(SOME_COMMAND) porque VAR=() é uma definição de array, então você precisa VAR=( $(echo 'Some value') ) .

    
por 22.10.2018 / 16:47