549 Stimmen

Warum ist manchmal Leerzeichen um Metazeichen erforderlich?

Vor ein paar Monaten habe ich eine Fork-Bombe auf meinen Arm tätowiert und die Leerzeichen weggelassen, weil ich denke, dass es ohne schöner aussieht. Aber zu meinem Ärger startet manchmal (nicht immer), wenn ich es in einer Shell ausführe, keine Fork-Bombe, sondern es gibt nur einen Syntaxfehler.

bash: Syntaxfehler in der Nähe des unerwarteten Tokens `{':

Gestern ist dies passiert, als ich versucht habe, es in der Bash-Shell eines Freundes auszuführen, und dann habe ich die Leerzeichen hinzugefügt und plötzlich hat es funktioniert, :(){ :|:& };: anstelle von :(){:|:&};:

Spielt das Leerzeichen eine Rolle; habe ich einen Syntaxfehler auf meinen Arm tätowiert?!

Es scheint immer in der zsh zu funktionieren, aber nicht in Bash.

Eine verwandte Frage erklärt nichts über die Leerzeichen, was wirklich meine Frage ist; Warum wird das Leerzeichen benötigt, damit Bash es korrekt analysieren kann?

271voto

Dmitri Chubarov Punkte 15283

Es gibt eine Liste von Zeichen, die Token in BASH trennen. Diese Zeichen werden als Metazeichen bezeichnet und sie sind |, &, ;, (, ), <, >, Leerzeichen und Tabulator. Andererseits sind geschweifte Klammern ({ und }) nur gewöhnliche Zeichen, die Wörter bilden.

Das Weglassen des zweiten Leerzeichens vor } wird tun, da & ein Metazeichen ist. Daher sollte Ihr Tattoo mindestens ein Leerzeichen enthalten.

:(){ :|:&};:

85voto

SzG Punkte 11697

Nur ein Tattoo a

#!/bin/zsh

shebang darüber setzen und du wirst in Ordnung sein.

50voto

Peter Westlake Punkte 4620

Klammern sind eher wie ungewöhnliche Schlüsselwörter als spezielle Symbole und benötigen Leerzeichen. Dies unterscheidet sich zum Beispiel von Klammern. Vergleichen Sie:

(ls)

welches funktioniert, und:

{ls}

welches nach einem Befehl namens {ls} sucht. Um zu funktionieren, muss es so sein:

{ ls; }

Das Semikolon verhindert, dass die schließende Klammer als Parameter für ls genommen wird.

Alles, was Sie tun müssen, ist den Leuten mitzuteilen, dass Sie eine proportional Schriftart mit einem ziemlich schmalen Leerzeichen verwenden.

40voto

Jerry Coffin Punkte 452852

Auch wenn es in der Tätowierungsschrift nicht leicht sichtbar ist, gibt es tatsächlich ein Byte-Reihenfolgezeichen (BOM) zwischen der geschweiften Klammer und dem Doppelpunkt (möglicherweise waren Sie ausreichend betrunken, als Sie die Tätowierung bekommen haben, dass Sie es nicht bemerkt haben, aber es ist wirklich da). Dies lässt drei offensichtliche Möglichkeiten:

  1. Sie haben das BOM nicht eingegeben, als Sie den Code transkribiert haben. Das Ergebnis ist eine offensichtliche Anwendung von GIGO. Die Shell erkennt einfach kein BOM, das nicht in Ihrer fehlerhaften Transkription enthalten ist.
  2. Ihre Shell ist zu alt. Sie erkennt keine Unicode-Zeichen, daher wird das BOM (und wahrscheinlich alle anderen Unicode-Zeichen) komplett ignoriert, obwohl ein BOM überall außer am Anfang einer Datei als ein nullbreiter, nicht umbrechender Leerzeichen behandelt werden sollte.
  3. Ihre Shell ist zu neu. Die Verwendung eines BOM als ZWNBS ist veraltet, und die Autoren haben eine zukünftige Version von Unicode implementiert, in der diese Verwendung nicht mehr erlaubt ist.

39voto

devnull Punkte 110398

und dann fügte ich das Leerzeichen hinzu und plötzlich funktionierte es ...

Das liegt daran, wie die Shell analysiert. Sie benötigen ein Leerzeichen, nachdem die Funktionendefinition beginnt, d.h. nach dem {.

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}

sind gültig. Andererseits ist

foo() {echo hey&}

nicht gültig.


Sie benötigen tatsächlich ein Tattoo wie dieses:

Geben Sie hier eine Bildbeschreibung ein


Aus der Quelle:

  /* Wir ignorieren eine geschweifte Klammer, die von Leerzeichen umgeben ist, und auch
     eine geschweifte Klammer, die sofort von einer geschlossenen Klammer gefolgt wird, die von Leerzeichen umgeben ist.  */

Ein Weglassen eines Leerzeichens nach dem { führt dazu, dass das {echo als ein einziges Token interpretiert wird.


Eine äquivalente Form von

:(){ :|:& };:

wäre

:(){
:|:& };:

Beachten Sie, dass es im alternativen Version kein Leerzeichen nach { gibt, aber ein Zeilenumbruch bewirkt, dass die Shell { als Token erkennt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X