function foo {
(cd $FOOBAR;
<some command>
if [$? -ne 0]
then
echo "Nope!"
else
echo "OK!"
fi
)
}
Ich versuche, eine Funktion wie die oben beschriebene zu schreiben und in meine .bashrc-Datei einzufügen. Nachdem ich die Datei bezogen und ausgeführt habe, erhalte ich:
Gesamtzeit: 51 Sekunden
-Bash: [1: Befehl nicht gefunden
OK!
Kann mir jemand helfen zu verstehen, was ich falsch gemacht habe?
$?
mit einerif
Anweisung gleich 0 ist, ist sinnlos,if
erwartet einen Befehl und wenn der Befehl zurückgegeben wird0
, wird der Code im Block ausgeführt. Alsoif true; then echo hello; fi
wird Hallo hallo, da der Befehltrue
zurückgegeben wurde0
.$?
Enthält den Status der letzten Pipeline , die nicht der Befehltest
([
) in derif
Anweisung ist. Das Beispiel testet, obsome command
es erfolgreich war. Sie können dasselbe mit&&
und tun||
, aber es können im Vergleich zu lange, unlesbare Zeilen entstehenif [ $? -eq 0 ]
. Das gleiche Argument gilt fürif some command
$?
weise darauf hin, dass es keinen Sinn macht,test
es zu verwenden. daif some command
macht das gleiche mit einer Aussage im Vergleich zu zwei getrennten Aussagen. Wenn der Befehl bereits lang ist, würde das Hinzufügen von drei weiteren Zeichen das "unlesbare" nicht schrecklich "unlesbarer" machen.Antworten:
Fügen Sie ein Leerzeichen nach dem
[
und ein weiteres vor]
:[
ein Shell - builtin ist, ist es ein Befehl wieecho
,read
,expr
... es einen Raum , nachdem er braucht, und erfordert eine passende]
.Schreiben
[ $? -ne 0 ]
ist tatsächlich aufgerufen wird[
und es vier Parameter geben:$?
,-ne
,0
, und]
.Hinweis: Die Tatsache, dass Sie eine Fehlermeldung erhalten,
[1: command not found
bedeutet,$?
dass der Wert von angegeben wurde1
.quelle
[
ist ein Link zutest
als auch[
eine eingebaute Shell und/usr/bin/[
wird nur selten verwendet.Oder Sie könnten
$?
ganz überspringen . Wenn Ihr Befehl lautetcmd
, sollte Folgendes funktionieren:quelle
Es wird empfohlen, den Rückgabewert einer Variablen zuzuweisen, bevor Sie ihn verwenden
Sie können den Rückgabewert wiederverwenden. zB in einer if ... elif ... else ... Anweisung.
quelle
[
(Ohne das Leerzeichen wird es zu einem Syntaxfehler inbash
) Wird rückgängig gemacht, wenn Sie Ihren Fehler bearbeiten und beheben.$?
direkt zu verwenden, da dies unterbrochen wird, wenn Sie beim späteren Bearbeiten des Skripts jemals eine Zeile zwischen dem Befehl und der$?
Prüfung einfügen.Der einzige Grund, warum Sie
$?
als Argumente für einen[
Befehl verwenden möchten (unabhängig davon, ob dieser[
Befehl im Bedingungsteil einerif
Anweisung ausgeführt wird oder nicht), besteht darin, dass Sie einen bestimmten Rückgabestatus unterscheiden möchten, z.Die Syntax für alle diejenigen
if
,while
,until
... AussagenWelches läuft,
cmd-list2
wenncmd-list1
es erfolgreich ist odercmd-list3
nicht.Der
[ "$?" -eq 0 ]
Befehl ist ein No-Op. Es wird$?
auf 0 gesetzt, wenn$?
0 ist, und$?
auf ungleich Null, wenn es nicht Null war.Wenn Sie etwas ausführen möchten, wenn es
cmd
fehlgeschlagen ist, ist es:Im Allgemeinen müssen Sie nicht basteln,
$?
geschweige denn wissen, welcher Wert bedeutettrue
oderfalse
. Die einzigen Fälle sind, wie oben erwähnt, wenn Sie einen bestimmten Wert unterscheiden müssen oder wenn Sie ihn für später speichern müssen (um ihn beispielsweise als Rückgabewert einer Funktion zurückzugeben), wie:Denken Sie auch daran, dass der Operator split + glob eine Variable ohne Anführungszeichen bleibt. Es ist nicht sinnvoll, diesen Operator hier aufzurufen, daher sollte es sein:
nicht
, geschweige denn[ $? -ne 0 ]
(was den[$? -ne 0 ]
[
Befehl nur aufrufen würde, wenn$IFS
es das erste Zeichen von enthalten würde$?
).Beachten Sie auch, dass die Bourne-Methode zum Definieren einer Funktion darin besteht,
function-name()
vor einem Befehl zu bleiben . Das ist der Fall in jedem Bourne wie Shell außerbash
undyash
(und neueren Versionen vonposh
) , die nur einer Verbindung Befehl (Verbindung Befehle zu sein erlauben{...}
oder(...)
oder Dinge wiefor...done
,if...fi
...function foo { ... }
ist dieksh
Syntax der Funktionsdefinition. Es gibt keinen Grund, warum Sie es hier verwenden möchten.Ihr Code kann portabel (POSIXly) geschrieben werden:
Beachten Sie auch, dass
cd
without-P
eine ganz besondere Bedeutung hat (behandelt Pfade, die..
Komponenten enthalten, die sich von anderen Befehlen unterscheiden). Daher ist es besser, sie in Skripte aufzunehmen, um Verwirrungen zu vermeiden.(Diese Funktion wird zurückgegeben,
false
wenn siecd
fehlschlägt, aber nicht, wenn sie<some command>
fehlschlägt.)quelle
Ich glaube, der folgende Befehl wird alles, was Sie wollen, in einer Zeile tun.
quelle