Befehl nicht gefunden Fehler in Bash-Variablenzuweisung

520

Ich habe dieses Skript namens test.sh:

#!/bin/bash
STR = "Hello World"
echo $STR

Wenn ich renne, sh test.shbekomme ich folgendes:

test.sh: line 2: STR: command not found

Was mache ich falsch? Ich schaue mir extrem einfache / Anfänger-Bash-Scripting-Tutorials online an und so sagen sie, dass sie Variablen deklarieren sollen ... Ich bin mir also nicht sicher, was ich falsch mache.

Ich bin auf Ubuntu Server 9.10. Und ja, Bash befindet sich bei /bin/bash.

Jake Wilson
quelle
49
Ich bin froh, dass du die Frage gestellt hast, du bist nicht der einzige Bash Noob da draußen!
Miller der Gorilla
6
Vielen Dank, dass Sie diese Frage gestellt haben. Dies ist keine Frage, über die man sich schämen sollte. Ich arbeite spät in der Nacht im Büro und es gibt keinen Bash-Experten um mich herum, der darauf antwortet.
Adway Lele
3
In diesen Tagen (fast sieben Jahre später!) Gibt es einen FOSS-Linter / Analysator namens Shellcheck , der dieses und andere häufig auftretende Syntaxprobleme automatisch erkennt. Es kann online verwendet oder offline installiert und in Ihren Editor integriert werden.
andere Typ
Ich würde Sie zu verwenden empfehlen: #!/usr/bin/env bashanstatt direkt setzen , #!/bin/bashes sei denn , du bist absolut sicher , dass Ihr bashheißt in /binwegen dieser Antwort: stackoverflow.com/a/21613044/3589567
Alejandro Blasco

Antworten:

929

Sie dürfen keine Leerzeichen um Ihr '=' - Zeichen haben.

Wenn Sie schreiben:

STR = "foo"

bash versucht einen Befehl namens STR mit 2 Argumenten auszuführen (die Zeichenfolgen '=' und 'foo')

Wenn Sie schreiben:

STR =foo

bash versucht einen Befehl namens STR mit 1 Argument auszuführen (der String '= foo')

Wenn Sie schreiben:

STR= foo

bash versucht, den Befehl foo auszuführen, wobei STR auf die leere Zeichenfolge in seiner Umgebung gesetzt ist.

Ich bin mir nicht sicher, ob dies zur Klärung beiträgt oder ob es sich lediglich um eine Verschleierung handelt, aber beachten Sie Folgendes:

  1. Der erste Befehl ist genau äquivalent zu: STR "=" "foo",
  2. der zweite ist der gleiche wie STR "=foo",
  3. und der letzte ist gleichbedeutend mit STR="" foo.

Der relevante Abschnitt der sh-Sprachspezifikation, Abschnitt 2.9.1, besagt:

Ein "einfacher Befehl" ist eine Folge von optionalen Variablenzuweisungen und -umleitungen in beliebiger Reihenfolge, optional gefolgt von Wörtern und Umleitungen, die von einem Steuerungsoperator beendet werden.

In diesem Zusammenhang ist a wordder Befehl, den bash ausführen wird. Jede Zeichenfolge, die =(an einer anderen Position als am Anfang der Zeichenfolge) keine Umleitung enthält, ist eine Variablenzuweisung, während jede Zeichenfolge, die keine Umleitung ist und keine enthält, =ein Befehl ist. In STR = "foo", STRist nicht eine variable Zuordnung.

William Pursell
quelle
2
Wenn Sie eine Variable mit einem Namen haben, der "-" enthält, tritt der gleiche Fehler auf. In diesem Fall besteht die Lösung darin, das "-"
Chomp am
1
chomp @ In Regel 7b von Abschnitt 2.10.10 von pubs.opengroup.org/onlinepubs/9699919799 "Wenn alle Zeichen vor '=' einen gültigen Namen bilden (siehe XBD-Name), wird das Token ASSIGNMENT_WORD zurückgegeben." Unter dem Link zu Abschnitt 3.231 von pubs.opengroup.org/onlinepubs/9699919799 finden wir "In der Shell-Befehlssprache ein Wort, das ausschließlich aus Unterstrichen, Ziffern und Alphabeten aus dem tragbaren Zeichensatz besteht. Das erste Zeichen eines Namens ist keine Ziffer. ". Das Wort FOO-BAR=quxist also keine Variablenzuweisung, da FOO-BARes sich nicht um einen gültigen Namen handelt.
William Pursell
2
Ich biete ein Kopfgeld an, um diese klare Erklärung für ein immer häufiges Problem für Anfänger zu belohnen (und auch, um es schneller zu finden, wenn ich es verknüpfen möchte: D). Danke, dass du es so einfach gemacht hast!
Fedorqui 'SO hör auf zu schaden'
1
@ Fedorqui Danke! Ich bin nicht ganz davon überzeugt, dass dies eine klare Erklärung ist, und ich frage mich oft, ob es einfacher gemacht werden könnte.
William Pursell
159

Lassen Sie die Leerzeichen um das =Schild fallen:

#!/bin/bash 
STR="Hello World" 
echo $STR 
Joey
quelle
9
Dies ist jedoch lustig, wie set foo = bares auch in Windows-Batchdateien ein häufiger Fehler ist - und dort wird die Batch-Sprache dafür lächerlich gemacht ;-)
Joey
Danke @joey. Ich war beim Schreiben eines Shell-Skripts festgefahren, bei dem ich Variablen mit Leerzeichen nach "=" initialisierte. Du hast meinen Tag gerettet
Lalit Rao
Warum akzeptiert bash keine Zahlen im linken Feld? wie 3 = "Hallo Welt", beschwert es sich über Befehl nicht gefunden
Freedo
6

Im interaktiven Modus sieht alles gut aus:

$ str="Hello World"
$ echo $str
Hello World

Offensichtlich (!) Wie Johannes sagte, kein Platz um =. Falls =in der Nähe ein Leerzeichen vorhanden ist, werden im interaktiven Modus Fehler als angezeigt

Kein Befehl 'str' gefunden

Arkapravo
quelle
2
Beachten Sie jedoch, dass das OP sagte STR = "Hello World", dass diese Antwort hier nicht gilt.
Fedorqui 'SO hör auf zu schaden'
@Arkapravo Was ist die Bedeutung des interaktiven Modus, ist es etwas mit der $Marke zu tun
Kasun Siyambalapitiya
@KasunSiyambalapitiya bedeutet "interaktiver Modus", dass diese Befehle im eigentlichen Terminal und nicht in ein Skript eingegeben werden.
Numbermaniac
5

Ich weiß, dass dies mit einer sehr hochwertigen Antwort beantwortet wurde. Aber kurz gesagt, Sie können keine Leerzeichen haben.

#!/bin/bash
STR = "Hello World"
echo $STR

Hat wegen der Leerzeichen um das Gleichheitszeichen nicht funktioniert. Wenn du rennen würdest ...

#!/bin/bash
STR="Hello World"
echo $STR

Es würde funktionieren

Derek Haber
quelle
2

Wenn Sie eine Variable definieren, müssen Sie keine zusätzlichen Leerzeichen einfügen.

Z.B

name = "Stack Overflow"  
// it is not valid, you will get an error saying- "Command not found"

Entfernen Sie also Leerzeichen:

name="Stack Overflow" 

und es wird gut funktionieren.

Ravi Solanki
quelle