if, elif, else Anweisungsprobleme in Bash

358

Ich kann anscheinend nicht herausfinden, was das Problem mit der folgenden ifAussage in Bezug auf das elifund ist then. Denken Sie daran, dass sich das printfnoch in der Entwicklung befindet. Ich konnte es in der Erklärung noch nicht testen. Es ist also höchstwahrscheinlich falsch.

Der Fehler, den ich bekomme, ist:

./timezone_string.sh: line 14: syntax error near unexpected token `then'
./timezone_string.sh: line 14: `then'

Und die Aussage ist so.

if [ "$seconds" -eq 0 ];then
   $timezone_string="Z"
elif[ "$seconds" -gt 0 ]
then
   $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
else
   echo "Unknown parameter"
fi
StuStirling
quelle
7
Ich frage mich, warum wir die Aussage in und aber nicht in und auch im Allgemeinen brauchen . thenifelifelse
@ w17t, weil wir Bedingung von Sequenz trennen müssen.
Sasha
3
@codeforester Ich sehe nicht viel Logik darin, eine Frage mit
500.000
Die Verwendung einiger Tools zur automatischen Formatierung von Code kann Ihnen helfen, indem Sie automatisch Leerzeichen um die Klammern hinzufügen / entfernen. Sie können nach Plugins für Ihren Editor suchen.
Nj Subedi

Antworten:

453

Zwischen elifund fehlt ein Leerzeichen [:

elif[ "$seconds" -gt 0 ]

sollte sein

elif [ "$seconds" -gt 0 ]

Da ich sehe, dass diese Frage viele Ansichten erhält, ist es wichtig anzugeben, dass die folgende Syntax lautet:

if [ conditions ]
# ^ ^          ^

Dies bedeutet, dass um die Klammern Leerzeichen benötigt werden . Sonst funktioniert es nicht. Dies liegt daran , [selbst ist ein Befehl.

Der Grund , warum Sie nicht wie etwas zu sehen elif[: command not found(oder ähnlich) ist , dass nach dem Besuch ifund thenwird die Schale entweder suchen elif, elseoder fi. Es findet jedoch eine andere then(nach der falsch formatierten elif[). Erst nachdem die Anweisung analysiert haben würde (und eine Fehlermeldung wie ausgeführt elif[: command not foundAusgabe wäre).

fedorqui 'SO hör auf zu schaden'
quelle
33
Der Grund, warum die Klammern Leerzeichen benötigen, ist, dass sie nur Verknüpfungen für tatsächliche Programme sind (zumindest die erste Klammer, die zweite ist nur syntaktischer Zucker, wie ich es verstehe). Um dies zu verstehen, lesen Sie die aktuelle Manpage für die linke Klammer:$ man [
Michael Johansen
3
Soll dieser Beitrag nicht als Tippfehler geschlossen werden?
zx8754
3
@ zx8754 hätte sein können, aber es wurde kein kanonischer Weg, um diesen Fehler zu beheben, der sehr nützlich aussieht (360K-Ansichten und Zählen).
Fedorqui 'SO hör auf,'
3
Einige meiner Kollegen verstehen das Konzept eines "Leerzeichens" oder "Codierungsstils" nicht, daher ist dies möglicherweise kein Tippfehler.
Juzzlin
3
[ist eine Art Alias ​​für den Testbefehl. Aus diesem Grund ist das Leerzeichen erforderlich. if test "$seconds" -eq 0; then ... fiist äquivalent zu if [ "$seconds" -eq 0 ];then ... fi ]. @LeiYang man testist das, wonach Sie tatsächlich suchen
Melicerte
303

Sie haben einige Syntaxprobleme mit Ihrem Skript. Hier ist eine feste Version:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi
Anubhava
quelle
76
Seltsamerweise war dies das einzige vollständige und einfache bash "Wenn-Dann-Sonst" -Konstrukt, das ich bei Stackexchange leicht gefunden habe ... danke.
Wildcard
1
Einrückung ist optional. Der Dolmetscher kann (und sollte) sein #!/bin/sh.
3
@ Chinggis6 Totaler Unsinn, der Dolmetscher könnte sein #!/bin/sh, muss es aber nicht.
Camusensei
4
@Camusensei es ist kein totaler Unsinn, da shes stattdessen für eine höhere Kompatibilität verwendet werden kann (nicht alle * nix-Distributionen haben Bash als Standard-Shell (einige haben ksh oder ash, aber die meisten hängen vom Standard ab, um shzu funktionieren)
6
@ Chinggis6 Richtig, schlechte Wortwahl auf meiner Seite.
Camusensei
25

[ist ein Befehl (oder ein in einigen Shells eingebauter Befehl). Es muss durch Leerzeichen von der vorhergehenden Anweisung getrennt werden:

elif [
Choroba
quelle
3
Es wird durch eine eingebaute Bash ersetzt, aber Ihre Nachricht ist immer noch korrekt. Verwenden Sie type -a [, um das zu sehen.
Camusensei
Es ist auch eine Binärdatei, die mir immer seltsam erschien.
mr.zog
4

Ich würde Ihnen empfehlen, sich die Grundlagen der Konditionierung in Bash anzuschauen.

Das Symbol "[" ist ein Befehl und muss ein Leerzeichen enthalten. Wenn Sie nach Ihrem elif kein Leerzeichen eingeben, interpretiert das System elif [ als einen bestimmten Befehl, der zu diesem Zeitpunkt definitiv nicht das ist, was Sie möchten.

Verwendungszweck:

elif(A COMPULSORY WHITESPACE WITHOUT PARENTHESIS)[(A WHITE SPACE WITHOUT PARENTHESIS)conditions(A WHITESPACE WITHOUT PARENTHESIS)]

Kurz gesagt, bearbeiten Sie Ihr Codesegment wie folgt:

elif [ "$seconds" -gt 0 ]

Sie würden ohne Kompilierungsfehler in Ordnung sein. Ihr endgültiges Codesegment sollte folgendermaßen aussehen:

#!/bin/sh    
if [ "$seconds" -eq 0 ];then
       $timezone_string="Z"
    elif [ "$seconds" -gt 0 ]
    then
       $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
    else
       echo "Unknown parameter"
    fi
Mr. Weirdo
quelle
2

Fehlender Platz zwischen elifund [Pause Ihres Programms ist korrekt. Sie müssen es korrigieren und auschecken. Hier ist festes Programm:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

nützlicher Link zu dieser bash if else-Anweisung

John Walsh
quelle