Assegnazione del codice di uscita a una variabile locale della shell


Risposte:


58

local t1=$(exit 1) dice alla shell di:

  • eseguire exit 1in una subshell;
  • memorizza il suo output (come in, il testo che genera in output standard) in una variabile t1, locale alla funzione.

È quindi normale che t1finisca per essere vuoto.

( $()è noto come sostituzione dei comandi .)

Il codice di uscita è sempre assegnato a $?, quindi puoi farlo

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

per ottenere l'effetto che stai cercando. Ovviamente puoi assegnare $?ad un'altra variabile:

function0()
{
  (exit 1)
  local t1=$?
  echo "$t1"
}

1
Sai, puoi sempre mettere anche il ritorno nel tubo. `$ (trap 'printf" :: ERRNO: $? "' 0; # ora fa comunque qualunque cosa - quella trap assicurerà che l'ultima stringa scritta sia l'ultimo ritorno per l'intero contesto di sostituzione.
mikeserv

1
@mikeserv ti sei perso un backtick? $(trap 'printf "::ERRNO:$?"' 0; # now do whatever however
Doktor J,

12

Il codice di uscita è stato memorizzato in $? variabile. Utilizzando Command Substitution solo catturare l'output, dovresti usare (...) per creare subshell :

#!/bin/bash

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

func

il punto del compito t1=$?è usarlo, no? e non $?saresti bloccato dall'operazione di assegnazione? Immagino che sto chiedendo se non dovrebbe essereprintf '%d\n' "${t1}"
Dani_l

@Dani_l: Grazie, è un errore di battitura. Aggiornato.
cuonglm,

Si noti che la sostituzione dei comandi cattura lo standard solo se reindirizzato in modo diverso.
Phyatt,

7

In bashquesto funziona:

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

Ha a che fare con l'ordine di valutazione dei comandi e l'assegnazione delle variabili. localha un valore di ritorno tutto suo - ed è il comando attualmente in esecuzione, non la sostituzione del comando. La ragione per cui cose come ...

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

... can return 1 è perché non c'è mai un ritorno in quel comando tranne che per l'esecuzione della subshell per assegnare $xil valore - quindi $?non viene bloccato come praticamente in ogni altro caso in cui vengono usate le sostituzioni di comandi.

In ogni caso, con localesso non vengono rovinati - ma se si cattura è proprio al momento giusto - che è, mentre le espansioni sono ancora in corso di valutazione e prima di local 's routine hanno la possibilità di clobber - si può ancora assegnare.

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

... stampe ...

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

Dovresti sapere però che in molte shell non puoi fare affidamento sull'impostazione della $?valutazione intermedia in quel modo. In effetti, probabilmente è perché quelle conchiglie non si preoccupano di rivalutare in ogni possibile congiuntura come forse bashfa - il che direi che probabilmente è un comportamento migliore di quello bash. Vuoi davvero che il tuo interprete valuti ricorsivamente i valori di valutazione che molto probabilmente saranno sovrascritti prima che tu abbia mai la possibilità di usarli?

Ad ogni modo, è così che puoi farlo.


-1

A seconda del motivo per cui stai solo cercando di ottenere il codice di uscita, puoi anche eseguirlo, il if some-command; then echo "Success $?"; else echo "Failure $?"; fiche non fa nulla con l'output del comando, ma valuta solo il codice di uscita dell'esecuzione del comando. È possibile aggiungere or( or$ ( around the command and you'll still get the same results. A better example might bese grep -q 'somestring' somefile; quindi echo "Il codice di uscita somestring trovato è $?"; Altrimenti "Il codice di uscita somestring è $?"; Fi`.

Puoi anche testare il codice di ritorno di una funzione che può essere un return 3codice di ritorno esplicito o implicito che è il risultato dell'ultimo comando, in questo caso devi fare attenzione a non avere un echoalla fine del funzione, altrimenti maschera / ripristina il precedente codice di uscita.

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 un trucco sporco dal momento che non puoi farlo VAR=(SOME_COMMAND)perché VAR=()è una definizione di array, quindi è necessario VAR=( $(echo 'Some value') ).


Tutti gli output dichiarati sono errati, a causa del fatto che la sostituzione dei comandi non fornisce il codice di uscita, che è l'intero punto della domanda. Non è chiaro cosa abbia a che fare il "trucco sporco" con qualsiasi cosa.
Nick Matteo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.