ubuntuusers.de

bash Skript - Syntaxfehler bei IF Abfrage

Status: Gelöst | Ubuntu-Version: Ubuntu 12.04 (Precise Pangolin)
Antworten |

verzweifelter-User

Anmeldungsdatum:
24. Juni 2012

Beiträge: 3

Hallo ihr Linux-Wissenden da draußen.

Ich schreibe gerade an meinem ersten bash-Skript (Ubuntu 12.04) und verzweifle gerade an dem Versuch eine simple if-Abfrage zu schreiben. Eigentlich dachte ich ja, dass könne kein Problem sein.

Mein test-Skript:

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo "Skript Anfang"
wert="Ja"
if [ $wert = "Ja" ]; then
	echo "Ja" ;
else
	echo "Nein" ;
fi
echo "Skript Ende"

Die Ausgabe dazu sieht dann so aus:

1
2
Skript Anfang
test.sh: Zeile 10: Syntax Fehler: Unerwartetes Dateiende.

Wenn ich die letzte echo-Zeile weglasse sagt er:

1
2
test.sh: Zeile 8: Syntaxfehler beim unerwarteten Wort `fi'
test.sh: Zeile 8: `fi'

Nach Allem, was ich so an Beispielen habe und dem was "help if" so sagt, sollte das eigentlich so tun.

☹ ☹ ☹

Kann mir jemand weiterhelfen?


Nebenbaustelle: Aus irgend einem Grund kann ich das Skript nur mit

1
bash test.sh

ausführen.

Bei

1
./test.sh

kommt die Meldung:

1
bash: ./test.sh: /bin/bash^M: Defekter Interpreter: Datei oder Verzeichnis nicht gefunden

Muss das Skript in einem bestimmten Verzeichnis liegen, damit das so klappt?

jplatte Team-Icon

Anmeldungsdatum:
28. November 2010

Beiträge: 1660

verzweifelter-User schrieb:

#!/bin/bash
echo "Skript Anfang"
wert="Ja"
if [ $wert = "Ja" ]; then
	echo "Ja" ;
else
	echo "Nein" ;
fi
echo "Skript Ende"

Also, zu...

1. Wenn du wert auf "Ja" überprüfen willst sieht das so aus:

if ($wert == "Ja")

Die eckigen Klammern benutzt man nur, wenn man zum Vergleich das Tool test benutzen will (ich glaube hauptsächlich für Dateien), siehe man test. Außerdem ist "=" der Operator zum Setzen, und "==" zum Vergleichen.

2. und 3. Das Semikolon schreibst du nur hinter einen Befehl, wenn du in der gleichen Zeile noch einen Befehl dahinter schreibst.

Bei

1
./test.sh

kommt die Meldung:

1
bash: ./test.sh: /bin/bash^M: Defekter Interpreter: Datei oder Verzeichnis nicht gefunden

Muss das Skript in einem bestimmten Verzeichnis liegen, damit das so klappt?

Vllt. hast du es einfach nicht als ausführbar markiert (Rechtsklick → Eigenschaften → Zugriffsrechte)?

u1000

Anmeldungsdatum:
2. Oktober 2011

Beiträge: 1850

verzweifelter-User schrieb:

1
bash: ./test.sh: /bin/bash^M: Defekter Interpreter: Datei oder Verzeichnis nicht gefunden

Das ^M zeigt, dass du die Datei test.sh mit einem Windows Editor erstellt hast - du hast jetzt statt Unix-Zeilumbrüchen Windows-Zeilenumbrüche in der Datei.

Lösung: schreibe deine Datei ganz neu mit einem Unix Editor (nano, leafpad, nedit usw.), konvertieren die Datei unter Unix mit dos2unix oder sage deinem Windows Programm (z.B. Ultraedit, Nodepad++) dass es Unix Zeilenenden (EOL) nutzen soll.

verzweifelter-User

(Themenstarter)

Anmeldungsdatum:
24. Juni 2012

Beiträge: 3

u1000 schrieb:

verzweifelter-User schrieb:

Lösung: schreibe deine Datei ganz neu mit einem Unix Editor (nano, leafpad, nedit usw.), konvertieren die Datei unter Unix mit dos2unix oder sage deinem Windows Programm (z.B. Ultraedit, Nodepad++) dass es Unix Zeilenenden (EOL) nutzen soll.

👍

Top!, Das war des Rätsels Lösung! Ich habe das jetzt noch mal komplett im vi runtergeschrieben und alle Probleme sind nichtig

😬 😬 😬

verzweifelter-User

(Themenstarter)

Anmeldungsdatum:
24. Juni 2012

Beiträge: 3

Jonessen96 schrieb:

verzweifelter-User schrieb: 1. Wenn du wert auf "Ja" überprüfen willst sieht das so aus:

if ($wert == "Ja")

Hm, den Teil mag er nicht:

Skript Anfang
./test.sh: Zeile 4: Ja: Kommando nicht gefunden.
Nein

Trotzdem danke.

Dank u1000 klappt das jetzt auch mit den eckigen Klammern und ich muss meinem Notepad++ nur noch beibringen im richtigen Format zu speichern.

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

Servus,

Jonessen96 schrieb:

1. Wenn du wert auf "Ja" überprüfen willst sieht das so aus:

if ($wert == "Ja")

Die eckigen Klammern benutzt man nur, wenn man zum Vergleich das Tool test benutzen will (ich glaube hauptsächlich für Dateien), siehe man test. Außerdem ist "=" der Operator zum Setzen, und "==" zum Vergleichen.

diesen Holzweg solltest du bei Gelegenheit verlassen. ☺

Das hier ist durchaus der richtige Test der klassischen Shell (was sich in heutigen POSIX-Shells wie der dash, die in Ubuntu als „/bin/sh“ rumliegt, wiederfindet):

1
2
3
4
if [ $foo = bar ]
then
	...
fi

(Mal ohne Betrachtung von Quoting und Fallstricken.)

Das einzelne Gleichheitszeichen ist nur in bestimmten Situationen ein Zuweisungsoperator. Zwei Gleichheitszeichen gab es ursprünglich als Test überhaupt nicht, erst die Bash kennt das aus „Kompatibilitätsgründen“, weil es in vielen anderen Sprachen auch so ist.

Richtig ist, dass „[“ früher mal ein externes Programm war. „if“ konnte da nur im Wesentlichen Exit-Codes von Programmen auswerten und kannte noch keine eigenen Tests. Aber Variableninhalte testet man auch in POSIX-Shells mit „[“, das ist nicht nur für Dateitests gedacht.

Heute ist „[“ ohnehin ein Shell-Builtin und es wird nicht mehr das externe Programm benutzt, obwohl es noch auf deiner Platte liegt:

$ ls -al /usr/bin/[
-rwxr-xr-x 1 root root 38660 May 12 05:28 /usr/bin/[

$ type [
[ is a shell builtin

Das heißt, „man test“ führt dich auch nicht zwangsläufig zu den richtigen Informationen über die Tests, die du damit durchführen kannst, weil sich das Shell-Builtin anders verhalten kann (auch, wenn es das eigentlich nicht sollte).

Die Bash kennt darüberhinaus auch noch „[[“, was man dem „[“ vorziehen kann, wenn man ein Bash-Skript schreibt, das nicht portabel sein muss. Das ist aber ein anderes Thema.

jplatte Team-Icon

Anmeldungsdatum:
28. November 2010

Beiträge: 1660

Danke für den Hinweis, zum Glück schreibe ich nicht allzu viele bash-scripts aber bisher haben die bei mir funktioniert. Ich bin mir zwar nicht sicher, ob ich es genauso gemacht hab wie ich es eben versucht habe zu erklären, aber egal 😀

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17599

Wohnort: Berlin

verzweifelter-User schrieb:

Hallo ihr Linux-Wissenden da draußen.

Ich schreibe gerade an meinem ersten bash-Skript (Ubuntu 12.04) und verzweifle gerade an dem Versuch eine simple if-Abfrage zu schreiben. Eigentlich dachte ich ja, dass könne kein Problem sein.

Mein test-Skript:

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo "Skript Anfang"
wert="Ja"
if [ $wert = "Ja" ]; then
	echo "Ja" ;
else
	echo "Nein" ;
fi
echo "Skript Ende"

Was Du auch gleich vergessen solltest ist, dass man in anderen Sprachen Textliterale grundsätzlich in Anführungsstriche packt, und dies in der Bash auch tut.

Tut man nicht.

Man verstellt sich so die Lernerfahrung, wo man Quotierung braucht und wo nicht.

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo Skript Anfang
wert=Ja
if [ $wert = "Ja" ]; then
	echo Ja
else
	echo Nein
fi
echo Skript Ende

Funktioniert genauso. Das Semikolon nach einem Befehl brauchst Du nur, wenn dem Befehl ein anderer in der gleichen Zeile folgt. Es ist quasi ein Ersatz für den Zeilenumbruch - entweder dies oder jenes.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

verzweifelter-User:

Herzlich willkommen noch hier auf dem Forum !


user unknown schrieb:

Was Du auch gleich vergessen solltest ist, dass man in anderen Sprachen Textliterale grundsätzlich in Anführungsstriche packt, und dies in der Bash auch tut.

Tut man nicht.

Man verstellt sich so die Lernerfahrung, wo man Quotierung braucht und wo nicht.

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo Skript Anfang
wert=Ja
if [ $wert = "Ja" ]; then
	echo Ja
else
	echo Nein
fi
echo Skript Ende

Funktioniert genauso. ...

Dieser pädagogische Ansatz ist ja ganz ok, allerdings solltest Du an bestimmten Stellen doch grundsätzlich "quoten". In diesem Fall wäre das in Zeile 4:

if [ "$wert" =  Ja  ]; then

Hier gibt es nämlich sonst sehr überraschende Fehler, wenn $wert später mal leer ist ! - probier es aus. (n.b.: die Gänsefüßchen um das "Ja" in der test-Klammer waren auch überflüssig ! - wenn schon, denn schon.)
Und dann als Programmierer später dem Benutzer zuzumuten, solch einen Fehler allein zu finden, wäre eben doch eine Zumutung ....

- meine 1½ Centen -

track

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

Wenn ihr schon davon anfangt, dann sagt doch auch dazu, was die Quotes denn tun, wenn sie schon keine Stringliterale einleiten. 😉

Quotes entfernen besondere Bedeutung von bestimmten Zeichen. Welche genau, steht da:

http://www.gnu.org/software/bash/manual/bashref.html#Quoting

Ein konkretes Beispiel der Vollständigkeit halber:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
foo=einWert

# Gibt den Wert aus:
echo $foo

# Eine Variante, um die besondere Bedeutung des Dollar-Zeichens
# aufzuheben, ist ein Backslash:
echo \$foo

# Eine andere Variante, um dasselbe zu erreichen, ist passendes
# Quoting des Dollar-Zeichens:
echo '$'foo

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17599

Wohnort: Berlin

track schrieb:

verzweifelter-User:

Herzlich willkommen noch hier auf dem Forum !


user unknown schrieb:

Was Du auch gleich vergessen solltest ist, dass man in anderen Sprachen Textliterale grundsätzlich in Anführungsstriche packt, und dies in der Bash auch tut.

Tut man nicht.

Man verstellt sich so die Lernerfahrung, wo man Quotierung braucht und wo nicht.

1
2
3
4
5
6
7
8
9
#!/bin/bash
echo Skript Anfang
wert=Ja
if [ $wert = "Ja" ]; then
	echo Ja
else
	echo Nein
fi
echo Skript Ende

Funktioniert genauso. ...

Dieser pädagogische Ansatz ist ja ganz ok, allerdings solltest Du an bestimmten Stellen doch grundsätzlich "quoten". In diesem Fall wäre das in Zeile 4:

if [ "$wert" =  Ja  ]; then

Hier gibt es nämlich sonst sehr überraschende Fehler, wenn $wert später mal leer ist ! - probier es aus.

Scripte verändern sich ja selten von selbst - in diesem fehlt solch eine Funktion. Wenn jemand das Script ändert ist es aber ein anderes. Es kann nicht durch eine Benutzerinteraktion $wert etwas anderes werden, sondern nur dadurch, dass jmd. das Script ändert - vor Änderungen schützt aber Deine Maßnahme nur, wenn eine ganz spezielle Änderung stattfindet - bei jeder anderen, etwa einer Änderung von $wert nach $wort hilft sie Dir auch nicht.

(n.b.: die Gänsefüßchen um das "Ja" in der test-Klammer waren auch überflüssig ! - wenn schon, denn schon.)

Ich war zu faul zu testen ob eine womöglich vorhandene Variable ja hier ohne $-Zeichen interpretiert würde. ☺

Und dann als Programmierer später dem Benutzer zuzumuten, solch einen Fehler allein zu finden, wäre eben doch eine Zumutung ....

Nein - wer Shellscripte schreibt mutet sich das immer noch selbst zu. Ich kann nicht für jedermann die Verantwortung übernehmen, der das tut und versuche es auch nicht.

Antworten |