920 Stimmen

Sind doppelte eckige Klammern [[ ]] gegenüber einfachen eckigen Klammern [ ] in der Bash vorzuziehen?

Ein Kollege behauptete kürzlich bei einer Codeüberprüfung, dass die [[ ]] Konstrukt ist zu bevorzugen gegenüber [ ] in Konstrukten wie

if [ "`id -nu`" = "$someuser" ] ; then
     echo "I love you madly, $someuser"
fi

Er konnte es nicht begründen. Gibt es eine?

32 Stimmen

Seien Sie flexibel, erlauben Sie sich manchmal, einen Ratschlag anzuhören, ohne dass Sie seine tiefgründige Erklärung benötigen :) Was die [[ damit ist der Code gut und klar, aber denken Sie an den Tag, an dem Sie Ihre Skriptwerke auf das System mit der Standard-Shell portieren werden, die nicht bash o ksh , usw. [ ist hässlicher und umständlicher, funktioniert aber wie AK-47 in jeder Situation.

404 Stimmen

@rook Man kann sich einen Ratschlag auch ohne eine ausführliche Erklärung anhören, klar. Aber wenn man um eine Erklärung bittet und sie nicht bekommt, ist das normalerweise ein Warnsignal. "Vertraue, aber überprüfe" und so weiter.

21 Stimmen

Siehe auch: [Was ist der Unterschied zwischen den Bash-Operatoren [[ vs [ vs ( vs ((?](https://unix.stackexchange.com/q/306111/201820) unter Unix und Linux SE.

23voto

Mark Reed Punkte 85468

Bei einer Frage mit dem Stichwort "Bash", die ausdrücklich "in Bash" im Titel hat, bin ich ein wenig überrascht von all den Antworten, die besagen, dass Sie Folgendes vermeiden sollten [[ ... ]] weil es nur in der Bash funktioniert!

Es stimmt, dass die Portabilität der primäre Einwand ist: Wenn Sie ein Shell-Skript schreiben wollen, das in Bourne-kompatiblen Shells funktioniert, auch wenn es sich nicht um Bash handelt, sollten Sie [[ ... ]] . (Und wenn Sie Ihre Shell-Skripte in einer strengeren POSIX-Shell testen wollen, empfehle ich dash Obwohl es eine unvollständige POSIX-Implementierung ist, da ihm die vom Standard geforderte Unterstützung für die Internationalisierung fehlt, fehlt ihm auch die Unterstützung für die vielen Nicht-POSIX-Konstrukte, die in bash, ksh, zsh usw. zu finden sind).

Der andere Einwand, den ich sehe, ist zumindest innerhalb der Annahme der Bash anwendbar: dass [[ ... ]] hat seine eigenen speziellen Regeln, die Sie lernen müssen, während [ ... ] verhält sich wie ein weiterer Befehl. Auch das ist wahr (und Herr Santilli hat die Belege für die Unterschiede vorgelegt), aber es ist ziemlich subjektiv, ob die Unterschiede gut oder schlecht sind. Ich persönlich finde es befreiend, dass ich mit dem Konstrukt der doppelten Klammer ( ... ) für die Gruppierung, && y || für boolesche Logik, < y > zum Vergleich, und nicht zitierte Parametererweiterungen. Es ist wie eine eigene kleine, abgeschlossene Welt, in der Ausdrücke eher wie in traditionellen, nicht auf der Kommandozeile basierenden Programmiersprachen funktionieren.

Ein Punkt, den ich noch nicht angesprochen habe, ist, dass dieses Verhalten der [[ ... ]] ist völlig konsistent mit dem Konstrukt der arithmetischen Erweiterung $(( ... )) die ist von POSIX spezifiziert, und erlaubt auch nicht in Anführungszeichen gesetzte Klammern sowie boolesche und Ungleichheitsoperatoren (die hier numerische statt lexikalische Vergleiche durchführen). Im Wesentlichen erhalten Sie jedes Mal, wenn Sie die doppelten Klammerzeichen sehen, den gleichen Anführungszeichen-Schutz-Effekt.

(Die Bash und ihre modernen Verwandten verwenden auch (( ... )) - ohne den führenden $ - entweder als eine C-Stil for Schleifen-Header oder eine Umgebung für die Durchführung von arithmetischen Operationen; keine der beiden Syntaxen ist Teil von POSIX).

Es gibt also einige gute Gründe, die dafür sprechen [[ ... ]] Es gibt auch Gründe, sie zu vermeiden, die in Ihrem Umfeld zutreffen können, aber nicht müssen. Was Ihren Kollegen betrifft, so ist "unser Styleguide sagt das so" eine gültige Rechtfertigung, soweit es geht, aber ich würde auch die Hintergründe von jemandem erfragen, der versteht, warum der Styleguide empfiehlt, was er tut.

6voto

Vicente Bolea Punkte 1285

Eine typische Situation, in der Sie Folgendes nicht verwenden können [[ ist in einem autotools configure.ac Skript. Dort haben die Klammern eine besondere und andere Bedeutung, so dass Sie Folgendes verwenden müssen test 代わりに [ o [[ -- Beachten Sie, dass Test und [ sind das gleiche Programm.

3 Stimmen

Da Autotools keine POSIX-Shell sind, warum sollten Sie jemals erwarten, dass [ als POSIX-Shell-Funktion definiert werden?

0 Stimmen

Denn das autoconf-Skript sieht aus wie ein Shell-Skript, und es erzeugt ein Shell-Skript, und die meisten Shell-Befehle funktionieren darin.

0voto

scavenger Punkte 367

[[ ]]-Doppelklammern werden unter bestimmten Versionen von SunOS und innerhalb von Funktionsdeklarationen völlig ununterstützt durch:

GNU Bash, Version 2.02.0(1)-Release (sparc-sun-solaris2.6)

1 Stimmen

Sehr wahr, und überhaupt nicht inkonsequent. bash Portabilität über ältere Versionen müssen berücksichtigt werden. Die Leute sagen "Bash ist allgegenwärtig und portabel, außer vielleicht für (hier esoterisches Betriebssystem einfügen) " -- aber meiner Erfahrung nach ist Solaris eine der Plattformen, bei denen der Portabilität besondere Aufmerksamkeit gewidmet werden muss: nicht nur, um ältere Bash-Versionen auf einem neueren Betriebssystem, Probleme/Bugs mit Arrays, Funktionen usw. zu berücksichtigen; aber auch Dienstprogramme (die in den Skripten verwendet werden) wie tr, sed, awk, tar haben Merkwürdigkeiten und Eigenheiten auf Solaris, die man umgehen muss.

2 Stimmen

Sie haben so recht... so viele Dienstprogramme nicht POSIX auf Solaris, schauen Sie sich nur die "df" Ausgabe und Argumente an... Eine Schande für Sun. Hoffentlich verschwindet es nach und nach (außer in Kanada).

12 Stimmen

Solaris 2.6 ernsthaft? Es wurde 1997 veröffentlicht und wird seit 2006 nicht mehr unterstützt. Ich schätze, wenn Sie es immer noch benutzen, dann haben Sie andere Probleme! Übrigens wurde Bash v2.02 verwendet, mit der die doppelten Klammern eingeführt wurden, also sollte es auch auf einem so alten System funktionieren. Solaris 10 von 2005 verwendet Bash 3.2.51 und Solaris 11 von 2011 verwendet Bash 4.1.11.

-1voto

unix4linux Punkte 57

Kurz gesagt, [[ ist besser, weil es keinen weiteren Prozess aufspaltet. Keine Klammern oder eine einzelne Klammer ist langsamer als eine doppelte Klammer, weil sie einen anderen Prozess forkt.

14 Stimmen

Test und [ sind Namen für denselben eingebauten Befehl in der Bash. Versuchen Sie es mit type [ um dies zu sehen.

1 Stimmen

@alberge, das ist richtig, aber [[ im Unterschied zu [ ist eine Syntax, die vom Bash-Befehlszeileninterpreter interpretiert wird. Versuchen Sie, in der Bash Folgendes einzugeben type [[ . unix4linux hat recht, obwohl die klassische Bourne-Shell [ Tests einen neuen Prozess abzweigen, um den Wahrheitswert zu ermitteln, wird der [[ Syntax (die von bash, zsh usw. von ksh übernommen wurde) nicht.

2 Stimmen

@Tim, ich bin mir nicht sicher, von welcher Bourne-Shell Sie sprechen, aber [ ist sowohl in Bash als auch in Dash eingebaut (die /bin/sh in allen von Debian abgeleiteten Linux-Distributionen).

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