Es gibt verschiedene Unterschiede. Meiner Meinung nach sind einige der wichtigsten:
[ist eine eingebaute in Bash und viele andere moderne Muscheln. Das eingebaute [ähnelt testmit dem zusätzlichen Erfordernis eines Schließens ]. Die eingebauten [und testimitierten Funktionen /bin/[und /bin/testderen Einschränkungen, so dass Skripte abwärtskompatibel wären. Die ursprünglichen ausführbaren Dateien sind größtenteils noch aus Gründen der POSIX-Kompatibilität und Abwärtskompatibilität vorhanden. Wenn Sie den Befehl type [in Bash [ausführen, wird dies standardmäßig als eingebaut interpretiert. (Hinweis: Sucht which [nur nach ausführbaren Dateien auf dem Pfad und ist äquivalent zu type -p [)
[[ist nicht so kompatibel, es wird nicht unbedingt funktionieren mit welchen /bin/shPunkten auch immer . So [[ist die modernere Bash / Zsh / Ksh-Option.
Da diese Funktion [[in die Shell integriert ist und keine älteren Anforderungen stellt, müssen Sie sich keine Gedanken über die Wortteilung auf der Grundlage der IFS- Variablen machen, um Variablen durcheinanderzubringen, die als Zeichenfolge mit Leerzeichen ausgewertet werden. Daher müssen Sie die Variable nicht in doppelte Anführungszeichen setzen.
Der Rest ist größtenteils nur eine nette Syntax. Um weitere Unterschiede zu sehen, empfehle ich diesen Link zu einer FAQ-Antwort: Was ist der Unterschied zwischen test, [und [[? . In der Tat empfehle ich, wenn Sie es mit Bash-Skripten ernst meinen, das gesamte Wiki zu lesen , einschließlich der FAQ, Fallstricke und Anleitung. Der Testabschnitt aus dem Handbuchabschnitt erklärt auch diese Unterschiede und warum die Autoren der Meinung [[sind, dass dies die bessere Wahl ist, wenn Sie sich keine Gedanken über die Mobilität machen müssen. Die Hauptgründe sind:
Sie müssen sich nicht darum kümmern, die linke Seite des Tests in Anführungszeichen zu setzen, damit er tatsächlich als Variable gelesen wird.
Sie müssen nicht kleiner als und größer als < >mit Backslashes umgehen, damit sie nicht als Eingabeumleitung gewertet werden, was einige Dinge durch das Überschreiben von Dateien durcheinander bringen kann. Dies geht wieder zurück zu [[einem eingebauten. Wenn [(test) ein externes Programm ist, müsste die Shell in der Art <und Weise, wie sie ausgewertet wird, eine Ausnahme machen und >nur, wenn /bin/testes aufgerufen wird, was eigentlich keinen Sinn ergibt.
Danke, der Link zu den Bash-FAQ war genau das, wonach ich gesucht habe (wusste nichts über diese Seite, danke).
0x89
2
Ich habe Ihren Beitrag mit diesen Informationen bearbeitet, aber [und Test werden als integrierte Elemente ausgeführt. Die Builtins sollten / bin / [und / bin / test ersetzen, aber auch die Einschränkungen der Binärdateien reproduzieren. Der Befehl 'type [' überprüft, ob das eingebaute Programm verwendet wird. 'which [' sucht nur im PATH nach ausführbaren Dateien und ist äquivalent zu 'type -P ['
klynch
133
Zusamenfassend:
[ist eine Bash Builtin
[[]] sind bash Keywords
Schlüsselwörter: Schlüsselwörter sind wie integrierte Schlüsselwörter, der Hauptunterschied besteht jedoch darin, dass für sie spezielle Analyseregeln gelten. Beispiel: [ist eine integrierte Bash, während [[ein Bash-Schlüsselwort ist. Sie werden beide zum Testen von Dingen verwendet, aber da [[kein eingebautes, sondern ein Schlüsselwort ist, profitieren sie von einigen speziellen Parsing-Regeln, die es viel einfacher machen:
$ [ a < b ]-bash: b:No such file or directory
$ [[ a < b ]]
Das erste Beispiel gibt einen Fehler zurück, weil bash versucht, die Datei b an den Befehl [a] umzuleiten. Das zweite Beispiel macht tatsächlich das, was Sie erwarten. Das Zeichen <hat keine spezielle Bedeutung mehr für den Operator "Dateiumleitung".
[ist ein POSIX-Shell-Befehl; Es muss nicht eingebaut werden. Es ]ist nur ein Argument, nach dem dieser Befehl sucht, damit die Syntax ausgewogen ist. Der Befehl ist ein Synonym für, testaußer dass er testnicht nach einem Abschluss sucht ].
[ ist nur ein regulärer Befehl mit einem seltsamen Namen.
]Dies ist nur ein Argument [, das die Verwendung weiterer Argumente verhindert.
Ubuntu 16.04 hat tatsächlich eine ausführbare Datei, /usr/bin/[die von coreutils zur Verfügung gestellt wird, aber die in Bash integrierte Version hat Vorrang.
An der Art und Weise, wie Bash den Befehl analysiert, ändert sich nichts.
Insbesondere werden durch <Umleitung &&und ||Verketten mehrerer Befehle ( )Unterschalen generiert, sofern diese nicht durch Escapezeichen geschützt werden \, und die Worterweiterung erfolgt wie gewohnt.
[[ X ]]ist ein einzelnes Konstrukt, das Xmagisch analysiert werden kann. <, &&, ||Und ()sind speziell, und einzelne Wörter aufgespalten Regeln behandelt unterschiedlich.
Es gibt auch weitere Unterschiede wie =und =~.
In Bashese: [ist ein integrierter Befehl und [[ein Schlüsselwort: https://askubuntu.com/questions/445749/was ist der Unterschied zwischen dem eingebauten Shell- und dem Shell - Schlüsselwort ?
<
[[ a < b ]]: lexikographischer Vergleich
[ a \< b ]: Das gleiche wie oben. \erforderlich oder führt die Umleitung wie bei jedem anderen Befehl aus. Bash-Erweiterung.
awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX-Äquivalent.
Empfehlung : immer verwenden [].
Für jedes [[ ]]Konstrukt, das ich gesehen habe, gibt es POSIX-Entsprechungen .
Wenn Sie Sie benutzen [[ ]]:
Portabilität verlieren
den Leser zwingen, die Feinheiten einer anderen Bash-Erweiterung zu lernen. [ist nur ein regulärer Befehl mit einem seltsamen Namen, es ist keine spezielle Semantik involviert.
¹ Inspiriert von dem entsprechenden [[...]]Konstrukt in der Korn-Shell
² schlägt jedoch für einige Werte von aoder b(wie +oder index) fehl und führt einen numerischen Vergleich durch, wenn aund bwie Dezimalzahlen aussehen. expr "x$a" '<' "x$b"funktioniert um beide.
³ und fällt auch für einige Werte von aoder bwie !oder aus (.
4 in Bash 3.2 und höher und vorausgesetzt, die Kompatibilität zu Bash 3.1 ist nicht aktiviert (wie bei BASH_COMPAT=3.1)
5 obwohl die Gruppierung (hier mit der {...;}Befehlsgruppe, statt der (...)eine unnötige Subshell ausgeführt werden würde) nicht erforderlich ist, da die Operatoren ||und die &&Shell (im Gegensatz zu den Operatoren ||und &&[[...]]oder den Operatoren -o/ -a[) den gleichen Vorrang haben. Wäre [ a = a ] || [ a = b ] && [ a = b ]also gleichwertig.
Wie benutzt man printf 'ab' | grep -Eq 'ab?'innerhalb if [ … ]?
MeeDamian
1
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. []ist ein Befehl wie grep. Das wird ()für diesen Befehl möglicherweise nicht benötigt. Ich bin mir nicht sicher: Ich habe es hinzugefügt, da es davon |abhängt, wie Bash die Dinge analysiert. Wenn es keine gäbe |, kannst du sicher nur schreiben if cmd arg arg; then.
Single Bracket dh []ist POSIX - Shell konform einen bedingten Ausdruck zu umschließen.
Doppel Brackets dh [[]]ist eine erweiterte (oder Erweiterung) Version von Standard - POSIX - Version, wird dies durch bash und andere Shells unterstützt wird (zsh, KSH).
In der bash für numerischen Vergleich verwenden wir eq, ne, ltund gt, mit doppelten Klammern zum Vergleich können wir verwenden ==, !=, <,und >buchstäblich.
[ist ein Synonym für Testbefehl. Selbst wenn es in die Shell integriert ist, wird ein neuer Prozess erstellt.
[[ ist eine neue verbesserte Version davon, die ein Schlüsselwort ist, kein Programm.
zum Beispiel:
[ var1 lt var2]#works[ var1 < var2]#error: var2 No such file or directory [ var1 \< var2]#works with escape[[ var1 < var2]]#works
Basierend auf einem schnellen Lesen der entsprechenden Abschnitte der manpage, erscheint der Hauptunterschied der zu sein , dass ==und !=Betreiber Spiel gegen ein Muster, anstatt eine Zeichenkette, und auch , dass die es =~regex Vergleichsoperator.
if
, obAntworten:
Es gibt verschiedene Unterschiede. Meiner Meinung nach sind einige der wichtigsten:
[
ist eine eingebaute in Bash und viele andere moderne Muscheln. Das eingebaute[
ähnelttest
mit dem zusätzlichen Erfordernis eines Schließens]
. Die eingebauten[
undtest
imitierten Funktionen/bin/[
und/bin/test
deren Einschränkungen, so dass Skripte abwärtskompatibel wären. Die ursprünglichen ausführbaren Dateien sind größtenteils noch aus Gründen der POSIX-Kompatibilität und Abwärtskompatibilität vorhanden. Wenn Sie den Befehltype [
in Bash[
ausführen, wird dies standardmäßig als eingebaut interpretiert. (Hinweis: Suchtwhich [
nur nach ausführbaren Dateien auf dem Pfad und ist äquivalent zutype -p [
)[[
ist nicht so kompatibel, es wird nicht unbedingt funktionieren mit welchen/bin/sh
Punkten auch immer . So[[
ist die modernere Bash / Zsh / Ksh-Option.[[
in die Shell integriert ist und keine älteren Anforderungen stellt, müssen Sie sich keine Gedanken über die Wortteilung auf der Grundlage der IFS- Variablen machen, um Variablen durcheinanderzubringen, die als Zeichenfolge mit Leerzeichen ausgewertet werden. Daher müssen Sie die Variable nicht in doppelte Anführungszeichen setzen.Der Rest ist größtenteils nur eine nette Syntax. Um weitere Unterschiede zu sehen, empfehle ich diesen Link zu einer FAQ-Antwort: Was ist der Unterschied zwischen test, [und [[? . In der Tat empfehle ich, wenn Sie es mit Bash-Skripten ernst meinen, das gesamte Wiki zu lesen , einschließlich der FAQ, Fallstricke und Anleitung. Der Testabschnitt aus dem Handbuchabschnitt erklärt auch diese Unterschiede und warum die Autoren der Meinung
[[
sind, dass dies die bessere Wahl ist, wenn Sie sich keine Gedanken über die Mobilität machen müssen. Die Hauptgründe sind:< >
mit Backslashes umgehen, damit sie nicht als Eingabeumleitung gewertet werden, was einige Dinge durch das Überschreiben von Dateien durcheinander bringen kann. Dies geht wieder zurück zu[[
einem eingebauten. Wenn [(test) ein externes Programm ist, müsste die Shell in der Art<
und Weise, wie sie ausgewertet wird, eine Ausnahme machen und>
nur, wenn/bin/test
es aufgerufen wird, was eigentlich keinen Sinn ergibt.quelle
Zusamenfassend:
Schlüsselwörter: Schlüsselwörter sind wie integrierte Schlüsselwörter, der Hauptunterschied besteht jedoch darin, dass für sie spezielle Analyseregeln gelten. Beispiel: [ist eine integrierte Bash, während [[ein Bash-Schlüsselwort ist. Sie werden beide zum Testen von Dingen verwendet, aber da [[kein eingebautes, sondern ein Schlüsselwort ist, profitieren sie von einigen speziellen Parsing-Regeln, die es viel einfacher machen:
Das erste Beispiel gibt einen Fehler zurück, weil bash versucht, die Datei b an den Befehl [a] umzuleiten. Das zweite Beispiel macht tatsächlich das, was Sie erwarten. Das Zeichen <hat keine spezielle Bedeutung mehr für den Operator "Dateiumleitung".
Quelle: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
quelle
[
ist ein POSIX-Shell-Befehl; Es muss nicht eingebaut werden. Es]
ist nur ein Argument, nach dem dieser Befehl sucht, damit die Syntax ausgewogen ist. Der Befehl ist ein Synonym für,test
außer dass ertest
nicht nach einem Abschluss sucht]
.Verhaltensunterschiede
Einige Unterschiede zu Bash 4.3.11:
POSIX vs Bash-Erweiterung:
[
ist POSIX[[
ist eine Bash-Erweiterung¹, die unter https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs dokumentiert istRegelmäßiges Kommando gegen Magie
[
ist nur ein regulärer Befehl mit einem seltsamen Namen.]
Dies ist nur ein Argument[
, das die Verwendung weiterer Argumente verhindert.Ubuntu 16.04 hat tatsächlich eine ausführbare Datei,
/usr/bin/[
die von coreutils zur Verfügung gestellt wird, aber die in Bash integrierte Version hat Vorrang.An der Art und Weise, wie Bash den Befehl analysiert, ändert sich nichts.
Insbesondere werden durch
<
Umleitung&&
und||
Verketten mehrerer Befehle( )
Unterschalen generiert, sofern diese nicht durch Escapezeichen geschützt werden\
, und die Worterweiterung erfolgt wie gewohnt.[[ X ]]
ist ein einzelnes Konstrukt, dasX
magisch analysiert werden kann.<
,&&
,||
Und()
sind speziell, und einzelne Wörter aufgespalten Regeln behandelt unterschiedlich.Es gibt auch weitere Unterschiede wie
=
und=~
.In Bashese:
[
ist ein integrierter Befehl und[[
ein Schlüsselwort: https://askubuntu.com/questions/445749/was ist der Unterschied zwischen dem eingebauten Shell- und dem Shell - Schlüsselwort ?<
[[ a < b ]]
: lexikographischer Vergleich[ a \< b ]
: Das gleiche wie oben.\
erforderlich oder führt die Umleitung wie bei jedem anderen Befehl aus. Bash-Erweiterung.expr a \< b > /dev/null
: POSIX-Äquivalent², siehe: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&&
und||
[[ a = a && b = b ]]
: wahr, logisch und[ a = a && b = b ]
: Syntaxfehler, der&&
als UND-Befehlstrennzeichen analysiert wirdcmd1 && cmd2
[ a = a -a b = b ]
: äquivalent, aber von POSIX³ veraltet[ a = a ] && [ b = b ]
: POSIX und zuverlässiges Äquivalent(
[[ (a = a || a = b) && a = b ]]
: falsch[ ( a = a ) ]
: Syntaxfehler,()
wird als Subshell interpretiert[ \( a = a -o a = b \) -a a = b ]
: äquivalent, wird aber()
von POSIX nicht mehr unterstützt{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX-Äquivalent 5Wortteilung und Generierung von Dateinamen bei Erweiterungen (split + glob)
x='a b'; [[ $x = 'a b' ]]
: true, keine Anführungszeichen erforderlichx='a b'; [ $x = 'a b' ]
: Syntaxfehler, erweitert auf[ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: Syntaxfehler, wenn sich mehr als eine Datei im aktuellen Verzeichnis befindet.x='a b'; [ "$x" = 'a b' ]
: POSIX-Äquivalent=
[[ ab = a? ]]
: true, weil es Pattern Matching macht (* ? [
sind magisch). Wird nicht global auf Dateien im aktuellen Verzeichnis erweitert.[ ab = a? ]
:a?
glob erweitert. Dies kann je nach den Dateien im aktuellen Verzeichnis wahr oder falsch sein.[ ab = a\? ]
: false, keine Glob-Erweiterung=
und==
sind in beiden[
und gleich[[
, ist aber==
eine Bash-Erweiterung.case ab in (a?) echo match; esac
: POSIX-Äquivalent[[ ab =~ 'ab?' ]]
: false 4 , verliert Magie mit''
[[ ab? =~ 'ab?' ]]
: wahr=~
[[ ab =~ ab? ]]
: true, POSIX- Übereinstimmung mit erweiterten regulären Ausdrücken ,?
Glob-Erweiterung nicht möglich[ a =~ a ]
: Syntax-Fehler. Kein Bash-Äquivalent.printf 'ab\n' | grep -Eq 'ab?'
: POSIX-Äquivalent (nur einzeilige Daten)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: POSIX-Äquivalent.Empfehlung : immer verwenden
[]
.Für jedes
[[ ]]
Konstrukt, das ich gesehen habe, gibt es POSIX-Entsprechungen .Wenn Sie Sie benutzen
[[ ]]
:[
ist nur ein regulärer Befehl mit einem seltsamen Namen, es ist keine spezielle Semantik involviert.¹ Inspiriert von dem entsprechenden
[[...]]
Konstrukt in der Korn-Shell² schlägt jedoch für einige Werte von
a
oderb
(wie+
oderindex
) fehl und führt einen numerischen Vergleich durch, wenna
undb
wie Dezimalzahlen aussehen.expr "x$a" '<' "x$b"
funktioniert um beide.³ und fällt auch für einige Werte von
a
oderb
wie!
oder aus(
.4 in Bash 3.2 und höher und vorausgesetzt, die Kompatibilität zu Bash 3.1 ist nicht aktiviert (wie bei
BASH_COMPAT=3.1
)5 obwohl die Gruppierung (hier mit der
{...;}
Befehlsgruppe, statt der(...)
eine unnötige Subshell ausgeführt werden würde) nicht erforderlich ist, da die Operatoren||
und die&&
Shell (im Gegensatz zu den Operatoren||
und&&
[[...]]
oder den Operatoren-o
/-a
[
) den gleichen Vorrang haben. Wäre[ a = a ] || [ a = b ] && [ a = b ]
also gleichwertig.quelle
printf 'ab' | grep -Eq 'ab?'
innerhalbif [ … ]
?if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi
.[]
ist ein Befehl wiegrep
. Das wird()
für diesen Befehl möglicherweise nicht benötigt. Ich bin mir nicht sicher: Ich habe es hinzugefügt, da es davon|
abhängt, wie Bash die Dinge analysiert. Wenn es keine gäbe|
, kannst du sicher nur schreibenif cmd arg arg; then
.()
scheint: stackoverflow.com/questions/8965509/…Single Bracket dh
[]
ist POSIX - Shell konform einen bedingten Ausdruck zu umschließen.Doppel Brackets dh
[[]]
ist eine erweiterte (oder Erweiterung) Version von Standard - POSIX - Version, wird dies durch bash und andere Shells unterstützt wird (zsh, KSH).In der bash für numerischen Vergleich verwenden wir
eq
,ne
,lt
undgt
, mit doppelten Klammern zum Vergleich können wir verwenden==
,!=
,<,
und>
buchstäblich.[
ist ein Synonym für Testbefehl. Selbst wenn es in die Shell integriert ist, wird ein neuer Prozess erstellt.[[
ist eine neue verbesserte Version davon, die ein Schlüsselwort ist, kein Programm.zum Beispiel:
quelle
Basierend auf einem schnellen Lesen der entsprechenden Abschnitte der manpage, erscheint der Hauptunterschied der zu sein , dass
==
und!=
Betreiber Spiel gegen ein Muster, anstatt eine Zeichenkette, und auch , dass die es=~
regex Vergleichsoperator.quelle