Wie extrahiert man den Exit-Status eines Befehls in eine Variable?

14

Ich habe vor ein paar Tagen angefangen, Bash zu lernen.

Ich versuche, einen Exit-Status des grepAusdrucks in eine Variable wie folgt zu erhalten :

check=grep -ci 'text' file.sh

und die Ausgabe, die ich bekam, ist

No command '-ic' found

Soll ich das mit einem Pipe-Befehl machen?

Omri Gilhar
quelle
6
Den Exit-Status können Sie $?direkt nach Beendigung des Befehls überprüfen .
coffeMug
und Sie können das PIPESTATUS-Array untersuchen, wenn Sie den Status eines der Befehle in einer Pipeline möchten.
cas

Antworten:

26

Ihr Befehl,

check=grep -ci 'text' file.sh

wird von der Shell als "den Befehl -cimit den Argumenten textund ausführen file.shund die Variable checkauf den Wert grepin ihrer Umgebung setzen" interpretiert .


Die Shell speichert den Exit-Wert des zuletzt ausgeführten Befehls in der Variablen ?. Sie können den Wert einer Ihrer eigenen Variablen wie folgt zuweisen:

grep -i 'PATTERN' file
check=$?

Wenn Sie auf diesen Wert reagieren möchten, können Sie entweder Ihre checkVariable verwenden:

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

oder Sie können mit einer separaten Variablen überspringen und müssen $?alles zusammen überprüfen :

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

(Beachten Sie -q, dass es anweist grep, nichts auszugeben und zu beenden, sobald etwas übereinstimmt; wir sind nicht wirklich daran interessiert, welche Übereinstimmungen hier vorhanden sind.)

Oder wenn Sie nur "Dinge tun" möchten, wenn das Muster nicht gefunden wird:

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

Das Speichern $?in eine andere Variable ist nur dann erforderlich, wenn Sie diese später verwenden müssen, wenn der Wert in $?wie in überschrieben wurde

mkdir "$dir"
err=$?

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

Im obigen Code-Snippet $?wird durch das Ergebnis des [ "$err" -ne 0 ] && [ ! -d "$dir" ]Tests überschrieben . Das Speichern hier ist nur dann wirklich notwendig, wenn wir es anzeigen und mit verwenden müssen exit.

Kusalananda
quelle
4

Ihre Frage ist unklar, aber basierend auf dem von Ihnen übermittelten Code soll die Variable checkden Beendigungsstatus des grepBefehls speichern . Der Weg, dies zu tun, ist zu laufen

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

Wenn Sie einen Befehl in einer Shell ausführen, wird der Beendigungsstatus über den speziellen Shell-Parameter verfügbar gemacht $?.

Dies wird von POSIX (dem Standard für Unix-ähnliche Betriebssysteme) in seiner Spezifikation für die Shell dokumentiert, und die Bash-Implementierung wird unter Special Parameters dokumentiert .

Da Sie ein neuer Lerner sind, empfehle ich Ihnen dringend, mit einem guten Buch und / oder einem Online-Tutorial zu beginnen, um die Grundlagen zu erlernen. Empfehlungen für externe Ressourcen werden auf Stack Exchange-Sites nicht empfohlen, ich empfehle jedoch Lhunath und GreyCats Bash Guide .

Anthony G - Gerechtigkeit für Monica
quelle
4

Sie haben bash angewiesen, die Variable check=grepin der Umgebung festzulegen, die an den Befehl übergeben wird

-ci 'text' file.sh

existiert aber cinicht.

Ich glaube, Sie wollten diesen Befehl in Back-Ticks oder in Klammern, denen ein Dollarzeichen vorangestellt ist, einschließen. In beiden Fällen wird die Anzahl der Zeilen angegeben, in denen "Text" (ohne Berücksichtigung der Groß- / Kleinschreibung) in der Datei gefunden wurde:

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

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

Jetzt $checksollte 0 sein, wenn keine Übereinstimmungen vorliegen, oder positiv, wenn Übereinstimmungen vorliegen.

Monty Harder
quelle
1

Verwirrt, warum -c verwendet wird, wenn die Ausgabe überprüft wird? Es wird verwendet, um zu überprüfen, wie oft etwas übereinstimmt - nicht, ob es erfolgreich ist oder nicht.

   -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.)

aber in diesem Beispiel

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

Es wird nur ein Exit-Code ausgegeben, der dann wiedergegeben wird. Dies ist die Ausgabe, die die Variablenprüfung verwendet. Ich bevorzuge es auch, weil es eine einzelne Zeile ist.

Sie können --silent durch -q ersetzen. Ich benutze es, da Sie nicht an der grep-Ausgabe interessiert sind, nur ob es funktioniert hat oder nicht.

   -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
Miati
quelle
1

Die korrekte Methode, um die Ausgabe des Befehls grep einer Variablen zuzuweisen, lautet wie folgt:

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

Um den Exit-Status dieses Befehls einer Variablen zuzuweisen, müssen Sie den Shell-Parameter $?direkt nach der Ausführung des Befehls verwenden, wie unten gezeigt:

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