Come si estrae lo stato di uscita di un comando in una variabile?


14

Ho iniziato a studiare Bash un paio di giorni fa.

Sto cercando di ottenere uno stato di uscita grepdell'espressione in una variabile come questa:

check=grep -ci 'text' file.sh

e l'output che ho ottenuto è

No command '-ic' found

Dovrei farlo con un comando pipe?


6
Per lo stato di uscita è possibile esaminare $?subito dopo che il comando è terminato.
coffeMug

e puoi esaminare l'array PIPESTATUS se vuoi lo stato di uno dei comandi in una pipeline.
CAS

Risposte:


26

Il tuo comando,

check=grep -ci 'text' file.sh

sarà interpretato dalla shell come "esegui il comando -cicon gli argomenti texte file.sh, e imposta la variabile checksul valore grepnel suo ambiente".


La shell memorizza il valore di uscita dell'ultimo comando eseguito nella variabile ?. Puoi assegnare il suo valore a una delle tue variabili come questa:

grep -i 'PATTERN' file
check=$?

Se vuoi agire su questo valore, puoi usare la tua checkvariabile:

if [ "$check" -eq 0 ]; then
    # do things for success
else
    # do other things for failure
fi

oppure potresti saltare usando una variabile separata e dover ispezionare $?tutti insieme:

if grep -q -i 'pattern' file; then
  # do things (pattern was found)
else
  # do other things (pattern was not found)
fi

(nota il -q, indica grepdi non produrre nulla e di uscire non appena qualcosa corrisponde; non siamo davvero interessati a ciò che corrisponde qui)

Oppure, se vuoi semplicemente "fare cose" quando il modello non viene trovato:

if ! grep -q -i 'pattern' file; then
  # do things (pattern was not found)
fi

Il salvataggio $?in un'altra variabile è sempre necessario solo se è necessario utilizzarlo in un secondo momento, quando il valore in $?è stato sovrascritto, come in

mkdir "$dir"
err=$?

if [ "$err" -ne 0 ] && [ ! -d "$dir" ]; then
    printf 'Error creating %s (error code %d)\n' "$dir" "$err" >&2
    exit "$err"
fi

Nel frammento di codice sopra, $?verrà sovrascritto dal risultato del [ "$err" -ne 0 ] && [ ! -d "$dir" ]test. Salvarlo qui è davvero necessario solo se dobbiamo visualizzarlo e usarlo con exit.


4

La tua domanda non è chiara ma in base al codice che hai inviato, sembra che desideri che la variabile checkmemorizzi lo stato di uscita del grepcomando. Il modo per farlo è eseguire

grep -ci 'text' file.sh
check=$?

Quando si esegue un comando da una shell, il suo stato di uscita viene reso disponibile tramite lo speciale parametro shell, $? .

Questo è documentato da POSIX (lo standard per sistemi operativi simili a Unix) nelle sue specifiche per la shell e l'implementazione di Bash è documentata in Parametri speciali .

Dal momento che sei un nuovo studente, ti consiglio vivamente di iniziare con un buon libro e / o tutorial online per ottenere le basi. I consigli sulle risorse esterne sono sconsigliati sui siti di Stack Exchange, ma suggerirei Bh Guide di Lhunath e GreyCat .


4

Hai detto a bash di impostare la variabile check=grepnell'ambiente che passa al comando

-ci 'text' file.sh

ma cinon esiste.

Credo che tu intendessi racchiudere quel comando tra i segni di spunta o tra parentesi precedute da un segno di dollaro, uno dei quali assegnerebbe il conteggio di quante righe 'testo' è stato trovato (senza distinzione tra maiuscole e minuscole) nel file:

check=`grep -ci 'text' file.sh`

check=$(grep -ci 'text' file.sh)

Ora $checkdovrebbe essere 0 se non ci sono corrispondenze o positivo se ci sono state corrispondenze.


1

Confuso perché usare -c quando si controlla l'output? Viene utilizzato per verificare quante volte viene abbinato qualcosa, non se ha successo o meno.

   -c, --count
          Suppress normal output; instead print a count of matching  lines
          for  each  input  file.  With the -v, --invert-match option (see
          below), count non-matching lines.  (-c is specified by POSIX.)

ma in questo esempio

check="$(grep --silent -i 'text' file.sh; echo $?)"

Non emette nulla tranne un codice di uscita, che viene poi ripetuto. Questo è l'output utilizzato dal controllo variabile. Lo preferisco anche perché è una riga singola.

È possibile sostituire --silent con -q. Lo uso perché non sei interessato all'output di grep, sia che abbia funzionato o meno.

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s  or  --no-messages  option.
          (-q is specified by POSIX.)

$ check=$(echo test | grep -qi test; echo $?) # check variable is now set
$ echo $check
0
$ check=$(echo null | grep -qi test; echo $?)
$ echo $check
1

1

Il modo corretto di assegnare l'output del comando grep a una variabile è come @ monty-harder menzionato:

check=`grep -ci 'text' file.sh`
check=$(grep -ci 'text' file.sh)

Sebbene per assegnare lo stato di uscita di questo comando a una variabile, è necessario utilizzare il parametro shell $?subito dopo aver eseguito il comando come mostrato di seguito:

grep -ci 'text' file.sh
check=$?
echo $check
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.