Wenn Sie eine Variable dereferenzieren bash
, müssen Sie $
sign verwenden. Dennoch scheint es, dass das Folgende gut funktioniert:
x=5
[[ x -gt 2 ]]
Kann das jemand erklären?
Bearbeiten: (mehr Info)
Ich meine, wie und warum der Befehl [[]] meine Variable x ohne das $ -Zeichen dereferenziert. Und ja, wenn x = 1, wird die Anweisung mit false bewertet (Rückgabestatus 1)
bash
bash-expansion
Gast
quelle
quelle
x=1
folgen[[ x -gt 2]]
?Antworten:
Der Grund ist, dass das
-eq
eine arithmetische Auswertung der Argumente erzwingt.Ein arithmetischer Operator:
-eq
,-gt
,-lt
,-ge
,-le
und-ne
in einem[[ ]]
(in KSH, zsh und bash) Mittel , um automatisch Variablennamen , wie in der C - Sprache zu erweitern, nicht für einen führenden benötigen$
.Zur Bestätigung müssen wir uns den Bash-Quellcode ansehen. Das Handbuch bietet keine direkte Bestätigung.
Innerhalb
test.c
der Verarbeitung von arithmetischen Operatoren fallen in diese Funktion:Wo
s
undt
sind beide Operanden. Die Operanden werden an diese Funktion übergeben:Die Funktion
evalexp
ist inexpr.c
der folgenden Kopfzeile definiert:Also, ja, beide Seiten eines arithmetischen Operators fallen (direkt) in die Auswertung von arithmetischen Ausdrücken. Direkt, kein Aber, kein Wenn.
In der Praxis mit:
Beides scheitert:
Was stimmt,
x
wird nicht erweitert undx
ist nicht gleich einer Zahl.Jedoch:
Die Variable mit dem Namen
x
wird erweitert (auch ohne $).Dies passiert nicht für a
[…]
in zsh oder bash (es passiert in ksh).Das ist dasselbe wie in einem
$((…))
:Und bitte haben Sie Verständnis dafür, dass dies (sehr) rekursiv ist (außer in Bindestrich und Yash):
A 😮
Und ziemlich riskant:
Der Syntaxfehler konnte leicht vermieden werden:
Wie das Sprichwort sagt: Desinfizieren Sie Ihre Eingabe
Ende von 😮
Sowohl das (ältere) Externe
/usr/bin/test
(nicht das eingebautetest
) als auch das noch ältere und auch das Externeexpr
erweitern Ausdrücke nicht nur Ganzzahlen (und anscheinend nur Dezimalzahlen):quelle
[[
Schlüsselwort werden Operatoren und Operanden beim Lesen des Befehls und nicht nach der Erweiterung erkannt. So[[
kann behandelt-eq
in einer intelligenten Art und Weise als, sagen sie,[
. Ich frage mich jedoch, wo wir Dokumentation über die Logik finden, mit der Bash zusammengesetzte Befehle interpretiert? Es sieht für mich nicht ganz offensichtlich aus und ich kann anscheinend keine zufriedenstellenden Erklärungen inman
oder findeninfo bash
.test
Die Operanden der numerischen Vergleiche
-eq
,-gt
,-lt
,-ge
,-le
und-ne
werden als arithmetischer Ausdrücke genommen. Mit einigen Einschränkungen müssen sie immer noch einzelne Shell-Wörter sein.Das Verhalten von Variablennamen im arithmetischen Ausdruck wird in Shell Arithmetic beschrieben :
und auch:
Aber ich kann den Teil der Dokumentation nicht finden, in dem es heißt, dass die numerischen Vergleiche arithmetische Ausdrücke annehmen. Es wird weder in Conditional Constructs unter
[[
noch in Bash Conditional Expressions beschrieben .Aber experimentell scheint es wie oben gesagt zu funktionieren.
Also, so etwas funktioniert:
auch dies (der Wert der Variablen wird ausgewertet):
Aber das tut es nicht. Es ist kein einzelnes Shell-Wort, wenn das
[[ .. ]]
geparst wird. Daher liegt ein Syntaxfehler in der Bedingung vor:In anderen arithmetischen Kontexten muss der Ausdruck kein Leerzeichen enthalten. Dies wird ausgegeben
999
, da die Klammern den arithmetischen Ausdruck im Index eindeutig abgrenzen:Andererseits ist der
=
Vergleich eine Musterübereinstimmung und beinhaltet weder Arithmetik noch die automatische Variablenerweiterung in einem arithmetischen Kontext (Bedingte Konstrukte):Das ist also falsch, da die Zeichenfolgen offensichtlich unterschiedlich sind:
wie folgt, obwohl die numerischen Werte gleich sind:
und auch hier werden die Saiten (
x
und6
) verglichen, sie sind unterschiedlich:Dies würde jedoch die Variable erweitern, so dass dies zutrifft:
quelle
arg1 OP arg2
besagt, dass die Args positive oder negative Ganzzahlen sein können, was meiner Meinung nach implizieren soll, dass sie als arithmetische Ausdrücke behandelt werden. Verwirrenderweise bedeutet dies auch, dass sie nicht Null sein können. :)[
, und dort gibt es keine arithmetischen Ausdrücke. Stattdessen beschwert sich Bash über Nicht-Ganzzahlen.[
ist ein externer Befehl, er hat keinen Zugriff auf Shell-Variablen. Es wird oft mit einem eingebauten Befehl optimiert, verhält sich aber trotzdem gleich.[
genau so gut wie[[
. Auch bei sind / müssen[
die Operanden to-eq
und friends ganze Zahlen sein, so dass auch die Beschreibung gilt. Das Nehmen von "Muss Ganzzahl sein", um "als arithmetische Ausdrücke interpretiert werden" zu bedeuten, gilt in beiden Fällen nicht. (Wahrscheinlich zumindest teilweise, weil Sie sich[
wie ein gewöhnlicher BefehlJa, Ihre Beobachtung ist korrekt. Die Variablenerweiterung wird für Ausdrücke in doppelten Klammern durchgeführt
[[ ]]
, sodass Sie keinen$
Variablennamen voranstellen müssen.Dies wird im
bash
Handbuch explizit angegeben :Beachten Sie, dass dies nicht der Fall ist
[ ]
, da[
es sich nicht um ein Shell-Schlüsselwort (Syntax) handelt, sondern um einen Befehl (in der Bash ist er eingebaut, andere Shells könnten externe, mit Zeilen versehene Tests verwenden).quelle
(x=1; [[ $x = 1 ]]; echo $?)
return0
,(x=1; [[ x = 1 ]]; echo $?)
return1
, dh die Parametererweiterung wird nicht ausgeführt,x
wenn Zeichenfolgen verglichen werden. Dieses Verhalten sieht aus wie eine arithmetische Auswertung, die durch eine arithmetische Erweiterung ausgelöst wird, dh was in passiert(x=1; echo $((x+1)))
. (man bash
In Bezug auf die arithmetische Auswertung heißt es: "In einem Ausdruck können Shell-Variablen auch namentlich referenziert werden, ohne die Parametererweiterungssyntax zu verwenden.)-gt
Operator eine Zahl erwartet, wird der gesamte Ausdruck neu ausgewertet, als ob er sich im Inneren befindet(())
, werden andererseits==
Zeichenfolgen erwartet, sodass stattdessen die Mustervergleichsfunktion ausgelöst wird. Ich habe mich nicht mit dem Quellcode befasst, aber es klingt vernünftig.[
ist eine in bash eingebaute Shell.