Klammern in if-Bedingung: Warum erhalte ich Syntaxfehler ohne Leerzeichen?

17

Ich verwende das folgende Skript, um zwei Tage zurück zu verschieben, wenn das Skript an zwei Tagen im Jahr ausgeführt wird. Außerdem überprüfe ich den ersten und zweiten Tag jedes Monats und verschiebe zwei Tage zurück.

if [$month="01"] && [$day="01"];
then
    date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
if [$month="01"] && [$day="02"];
then
         date="$last_month/$yes_day/$last_year"
      fulldate="$last_month/$yes_day/$last_year"
else
   if [ $day = "01" ];
then
    date="$last_month/$yes_day/$year"
            fulldate="$year$last_month$yes_day"
else
        if [ $day = "02" ];
then
    date="$last_month/$yes_day/$year"
        fulldate="$year$last_month$yes_day"
else
    date="$month/$yes_day/$year"
        fulldate="$year$month$yes_day"
                fi
               fi
              fi
fi

Aber mein schlechtes bekomme die folgende Fehlermeldung

Etime_script.sh: line 19: [06=01]: command not found
Etime_script.sh: line 24: [06=01]: command not found
Kumar1
quelle
1
Die gegebenen Antworten sind richtig; du brauchst ein Leerzeichen danach [. Überprüfen Sie außerdem die elifAnweisung. Es wird Ihnen helfen, die Dinge aufzuräumen. Auch die Semikolons nach den if-Anweisungen sind nicht notwendig, aber auch nicht falsch, nur seltsam.
Shawn J. Goff
@ ShawnJ.Goff Sie sind notwendig, wenn Sie die nächste Zeile verketten ( if [ ... ]; then), also nicht so ungewöhnlich.
Goldlöckchen
@goldilocks, ja, das ist mein bevorzugter Stil. Der Grund, warum es ungewöhnlich ist, ist, dass er das nicht tut.
Shawn J. Goff

Antworten:

27

[ist weder ein Metazeichen noch ein Steueroperator (nicht einmal ein reserviertes Wort; dasselbe für ]) und benötigt daher Leerzeichen. Andernfalls ist die Shell „sieht“ den Befehl [01=01]anstelle des Befehls [mit den separaten Parameter 01, =, 01, und ]. Jeder Operator und Operand muss ein separates Argument für den [Befehl sein, daher ist auch für die Operatoren ein Leerzeichen erforderlich.

if [ "$month" = "01" ]

[$month="01"]ist ein Platzhaltermuster, das mit einem der Zeichen in $monthoder übereinstimmt "01. Wenn es zu nichts passt, bleibt es in Ruhe.

Befindet sich nach der schließenden Klammer ein Semikolon, brauchen Sie kein Leerzeichen, da das Semikolon immer Teil eines separaten Tokens ist.

if [ "$month" = "01" ]; then

Gleiches gilt für die doppelte Klammersyntax von bash (und ksh und zsh).

Mehr als eine Bedingung

Es gibt zwei Möglichkeiten, Bedingungen zu kombinieren:

  1. innerhalb [

  2. mit separaten [Befehlen kombiniert mit &&oder||

Das Gruppieren mit Klammern ist innerhalb von wahrscheinlich einfacher [.

if [ "$month" = "01" -a "$day" = "01" ] # -a for and, -o for or

if [ "$month" = "01" ] && [ "$day" = "01" ]

Das erste sollte vermieden werden, da es unzuverlässig ist (versuchen Sie es zum Beispiel mit month='!'). Probleme mit seltsamem Variableninhalt können vermieden werden, indem zuerst die sichere Zeichenfolge (falls vorhanden) verwendet wird. oder mit [[/ ]]anstelle von [/ ]:

if [ "01" = "$month" -a "01" = "$day" ]
Hauke ​​Laging
quelle
Wie können wir die beiden Bedingungen erfüllen, wenn, wie Monatswert == Tageswert, wenn [$ month = "01"] && [$ day = "01"];
Ich
@AshokSanganahalli Ich habe meine Antwort erweitert.
Hauke ​​Laging
1
[Wenn -a/ -owerden nicht verwendet ist immer zuverlässig mit POSIX-kompatiblen Shells. Die Verwendung von -a/-oover hat keinerlei Vorteil &&/||. Ich würde definitiv von seiner Verwendung abraten. Beachten Sie, dass dies [[kein POSIX ist.
Stéphane Chazelas
4

Ein anderer Weg, es zu schreiben:

case $month:$day in
  (01:0[12])
    date="$last_month/$yes_day/$last_year"
    fulldate="$last_month/$yes_day/$last_year"
    ;;
  (*:0[12])
    date="$last_month/$yes_day/$year"
    fulldate="$year$last_month$yes_day"
    ;;
  (*)
    date="$month/$yes_day/$year"
    fulldate="$year$month$yes_day"
esac
Stéphane Chazelas
quelle
1
+1 für caseAussage. Wenn Sie mehr als eine haben elif, sollten Sie wahrscheinlich verwenden case.
HalosGhost
-1

Das ist also deine Antwort:

if [ $var1 == $var2 ];
 then
    echo "bla bla"
fi

Sie müssen also "Leerzeichen" zwischen eckige Klammer und Variable / Wert setzen.

Neven
quelle
Nein, ich schätze, weil ich Script gebeten habe, zwei Tage zurück zu verschieben, wenn Script an zwei Tagen im Jahr ausgeführt wird, und auch den ersten und zweiten Tag jedes Monats zu überprüfen und zwei Tage zurück zu verschieben, bedeutet hier, wenn [$ month = "01"] && [$ day = "01"] Wir nehmen an, dass Monat "01" und erster Tag "01"
übereinstimmen.
1
@AshokSanganahalli: Ich weiß nicht, wie das zusammenhängt, aber Ihre IF-Bedingung funktioniert nicht, weil Sie kein "Leerzeichen" zwischen eckigen Klammern und Wert haben
Neven
@AshokSanganahalli Es ist normalerweise keine gute Idee für Leute auf deinem Können, Korrekturen von Leuten mit offensichtlich besserem Verständnis zu bestreiten, ohne zumindest den Hinweis auszuprobieren. Wenn Ihre Vermutungen richtig wären, müssten Sie hier nicht nachfragen, oder?
Hauke ​​Laging
4
-1 für nicht in Anführungszeichen gesetzte Variablen und Verwendung von ==anstelle von standard =.
Stéphane Chazelas
2
Die Frage ist nicht bash markiert. Der Gleichheitsvergleichsoperator im Standard- [aka- testBefehl lautet =. [Wenn für Tests keine Zuordnung erforderlich ist, muss keine eindeutige Zuordnung vorgenommen werden. Einige [Implementierungen werden ==als Erweiterung des Standards unterstützt, jedoch nicht alle. Das Bourne - Shell sind, ash's, poshs [s oder die /bin/[von einigen Systemen zum Beispiel nicht. ==wurde hinzugefügt , indem kshich an , dass für die Übereinstimmung mit dem gleichen Betreiber in seinem neuen (( ... ))Konstrukt (die beide = hat und ==, aber es keinen Standard)
Stéphane Chazelas