In einigen Fällen spielt die Anzahl der Leerzeichen in Bash-Skripten (oder anderen Shell-Skripten) eine Rolle

14

Mir wurde gesagt, dass die Leerzeichen in bashoder in anderen Shell-Skripten wichtig sind, und ich sollte die Existenz von Leerzeichen nur ändern, wenn ich weiß, was ich tue. Mit "Ändern der Existenz" meine ich entweder das Einfügen eines Leerzeichens zwischen zwei Nicht-Leerzeichen oder das Entfernen eines Leerzeichens zwischen zwei Nicht-Leerzeichen, z. B. Ändern var="$val"in var ="$val"oder umgekehrt. Ich will fragen

Gibt es Fälle, in denen die Verwendung eines einzelnen Leerzeichens oder mehrerer aufeinanderfolgender Leerzeichen in einem Shell-Skript einen Unterschied macht? .

(Natürlich macht das Einfügen / Löschen eines Leerzeichens in Anführungszeichen einen Unterschied, z. B. das Ändern von echo "a b"nach echo "a b"oder umgekehrt. Ich suche nach Beispielen, die von diesem trivialen Beispiel abweichen .)

Ich bin auf diese Frage gestoßen, aber es geht um das Hinzufügen und Entfernen von Leerzeichen zwischen zwei Nicht-Leerzeichen, für die ich viele Beispiele kenne, die einen Unterschied machen würden.

Jede Hilfe wäre dankbar. Fügen Sie nach Möglichkeit weitere Sorten von Muscheln hinzu.

Weijun Zhou
quelle

Antworten:

19

Außerhalb von Anführungszeichen verwendet die Shell Leerzeichen (Leerzeichen, Tabulatoren, Zeilenvorschübe, Wagenrücklauf usw.) als Trennzeichen zwischen Wörtern und Token. Das bedeutet:

  • Dinge, die nicht durch Leerzeichen getrennt sind, werden als ein "Wort" betrachtet.
  • Dinge, die durch ein oder mehrere Leerzeichen getrennt sind, werden als zwei (oder mehr) Wörter betrachtet.

Die tatsächliche Anzahl von Whitespace-Zeichen zwischen den einzelnen "Dingen" spielt keine Rolle, solange mindestens eines vorhanden ist.

cas
quelle
Vielen Dank. Ich kann selbst kein Gegenbeispiel finden. Ich wollte nur sichergehen.
Weijun Zhou
2
Bash betrachtet Formular-Feeds und vertikale Tabulatoren auch als Leerzeichen.
fpmurphy
wahr. Ich schrieb ursprünglich '... newlines, etc' und änderte es dann explizit Wagenrücklauf hinzuzufügen. hat versehentlich das 'etc' fallen lassen.
cas
Was passiert, wenn die Anzahl der Speicherplätze so groß ist, dass das Programm nicht in den Speicher passt?
Worse_Username
7
@Worse_Username Das Leerzeichen muss nicht in den Speicher passen. Ich habe gerade ein 48-GB-Skript auf einem Computer mit 8 GB RAM und 20 GB Swap erstellt. Es lief gut. Es dauerte 3 Minuten, bis der gesamte Whitespace durchlaufen war, aber am Ende wurde ein echoBefehl mit so viel Whitespace zwischen dem Befehl und dem Argument erfolgreich ausgeführt.
Kasperd
23

Dies ist wahrscheinlich Betrug, aber das:

rm foo\ bar         # "delete the file named 'foo bar'"

unterscheidet sich von diesem:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

obwohl die Leerzeichen nicht in Anführungszeichen stehen. ;-)

Noch verwirrender ist dies:

rm \
    foo          # "delete the file named 'foo'"

unterscheidet sich von diesem:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

obwohl sie identisch aussehen !

ruakh
quelle
Obwohl die Leerzeichen nicht in Anführungszeichen stehen, ähnelt der umgekehrte Schrägstrich funktional der Form des Zitierens, und ich würde dies in dieselbe Kategorie wie das "triviale Beispiel" der Frage einordnen. (Es ist jedoch interessant.)
David Z
12

Wenn wir nicht über die Leerzeichen (sprechen U+0020) , aber jeder Leerzeichen ( U+0020, \n, \t, etc.), dann einen bestimmten Fall meiner Meinung nach kommen: Hier-Dokumente.

Dieser Code (mit Leerzeichen):

cat <<- 'EOF'
<space><space>foo
EOF

Druckt:

  foo

Aber dieser Code (mit Tabulatoren):

cat <<- 'EOF'
<tab><tab>foo
EOF

Druckt:

foo

Das liegt daran ( wie POSIX angibt ):

Wenn der Umleitungsoperator lautet <<-, werden alle führenden <tab> -Zeichen aus den Eingabezeilen und der Zeile mit dem abschließenden Trennzeichen entfernt.

nxnev
quelle
1
Das ist interessant. Ich habe über Dokumente nachgedacht, aber den <<-Betreiber nicht gekannt . Vielen Dank.
Weijun Zhou
Hier sind Dokumente eine Form von zitiertem Text, kein Shell-Code. Shell-Worttrennung gilt nicht.
cas
2

Dies wirkt sich auch beim Schreiben von Zuweisungsanweisungen aus. Zum Beispiel, wenn ich sage FOO=xyz, dass eine Umgebungsvariable mit dem Namen FOOvalue erstellt wird xyz, aber wenn ich die Gleichheit mit einem Leerzeichen trenne, wird angenommen, dass ich ein Programm FOOmit dem Namen arg aufrufe =xyz. Es ist also wichtig, wenn es um bestimmte Syntax geht.

HSchmale
quelle
Erstellt FOO=xyznormalerweise eine interne Shell-Variable, aber keine Umgebungsvariable. Sie benötigen set -aoder export FOO=xyzdafür (dh Sie machen es zu einem Teil der Umgebung von Nicht-Subshell-Subprozessen).
Hauke ​​Laging