GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Sind Bash-Tests so wählerisch in Bezug auf Leerzeichen?

Als hauptsächlich Java-Programmierer finde ich die Bash ifthen Konstrukt ziemlich verwirrend, insbesondere in Bezug auf Leerzeichen. Kann jemand erklären, warum das erste funktioniert, aber nicht das zweite oder dritte?

#works
if [ -n $1 ]; then echo "parameterized"; fi

#output: ./links: Zeile 1: [-n: Kommando nicht gefunden.
if [-n $1 ]; then echo "parameterized"; fi

#output: ./links: Zeile 1: [: Fehlende `]'
if [ -n $1]; then echo "parameterized"; fi

Akzeptierte Antwort:

Die Inkonsistenz ist größtenteils auf historische Gründe zurückzuführen.

Die Verwendung von Klammern als bedingter Befehl kam nach der Verwendung von Klammern in Platzhaltermustern. Also zum Zeitpunkt [ -n foo ] kam auf die Bildfläche, [foo] bedeutete bereits „eine Datei, deren Name f ist oder o “. Während nur wenige Verwendungen des Klammeroperators in der Praxis mit der realistischen Verwendung der Klammern in Platzhaltern in Konflikt geraten wären, entschieden sich die Autoren, nicht das Risiko einzugehen, vorhandene Skripte durch eine Änderung der Syntax zu beschädigen. Diese Designwahl erleichterte auch die Implementierung:anfänglich [ wurde als externer Befehl implementiert, was nicht möglich gewesen wäre, wenn das Leerzeichen nach [ war optional gewesen. (Moderne Systeme haben immer noch [ als externes Kommando, aber fast alle modernen Shells haben es auch eingebaut.)

Aus ähnlichen Gründen ist Ihr „funktionierender“ Code in den meisten Fällen tatsächlich falsch. $1 bedeutet nicht „den Wert von Parameter 1“:es bedeutet „nehmen Sie den Wert von Parameter 1, teilen Sie ihn in einzelne Wörter bei Leerzeichen (oder was auch immer der Wert von IFS ist ist) und interpretiere jedes Wort als Glob-Muster“. Um „den Wert von Parameter 1“ zu schreiben, sind doppelte Anführungszeichen erforderlich:"$1" . Siehe Wann sind doppelte Anführungszeichen erforderlich? für das nüchterne. Sie müssen das nicht verstehen; Sie müssen sich nur daran erinnern:Setzen Sie immer doppelte Anführungszeichen um Variablenersetzungen "$foo" und Befehlsersetzungen "$(foo)" . Also:

if [ -n "$1" ]; then …

In bash, ksh und zsh, aber nicht in einfachem sh, können Sie auch doppelte Klammern verwenden. Einfache Klammern [ … ] werden wie ein gewöhnlicher Befehl geparst (und tatsächlich [ ist ein gewöhnlicher Befehl, obwohl er normalerweise eingebaut ist). Doppelte Klammern sind ein separates syntaktisches Konstrukt und Sie können die doppelten Anführungszeichen meistens weglassen.

if [[ -n $1 ]]; then …

Es gibt jedoch eine Ausnahme:[[ "$foo" = "$bar" ]] Um zu testen, ob die beiden Variablen denselben Wert haben, sind doppelte Anführungszeichen um $bar erforderlich , andernfalls $bar wird als Platzhaltermuster interpretiert. Auch hier können Sie, anstatt sich an die Details zu erinnern, genauso gut die ganze Zeit doppelte Anführungszeichen verwenden.

Verwandte:Beginnend mit bash:Argumente -lt und -gt?
Linux
  1. Klammern in der If-Bedingung:Warum erhalte ich Syntaxfehler ohne Leerzeichen?

  2. Welche Funktionen sind in Zsh und fehlen in Bash oder umgekehrt?

  3. Was sind die Worttrennzeichen von Readline?

  4. Strings fehlen nach dem Verketten von zwei oder mehr variablen Strings in Bash?

  5. Welches sind die speziellen Parameter/Variablen der (Bash-)Shell?

Bash Shebang

Was ist ZFS? Warum sind die Leute verrückt danach?

Bash-If-Else-Anweisungen – Alles, was Sie wissen müssen

Nützliche Bash-Befehle, die Sie vielleicht nicht kennen

Löschen Sie Leerzeichen in jedem Zeilenanfang der Datei mit bash

Verstehen, wie Eingaben in Bash an Pipes gesendet werden