2016-10-18 1 views
1

Wenn ich arithmetische Erweiterung in einem Array-Index in bash, wie folgt aus:Bash: arithmetische Expansion in Array-Indizes - wird das Dollarzeichen benötigt?

declare -a FILES 
declare -i INDEX=0 

for FILE in ./* 
do 
    FILES[((INDEX++))]="$FILE" 
done 

Benötige ich ein Dollarzeichen vor ((...))?
So muss es sein:

FILES[((INDEX++))]="$FILE" 

oder besser gesagt:

FILES[$((INDEX++))]="$FILE" 

?
In meiner lokalen Kopie von bash scheinen beide Varianten zu funktionieren - es ist Version 4.3.30.
Ich würde erwarten, dass nur letzteres funktioniert, weil ich denke, dass nur das Ergebnis des arithmetischen Ausdrucks zurückgibt. Aber da: Bash - arithmetic in array index Ich habe gelesen, dass nur der erste mit älteren Versionen von bash (?) Funktionieren könnte. Also welches ist eigentlich richtig? Und warum funktioniert der erste? Ich habe darauf noch keine spezifische Antwort gefunden.

+0

In der Frage, die Sie verbunden sind, wurde das Problem nicht auf die Version von 'bash' bezogen. Der Benutzer hatte einen Fehler in seinem Skript ('über das Versions-Problem, vergiss es ... Ich fand heraus, dass x leer ist, wenn der Fehler erreicht ist'). – Aserre

+0

@Aserre: Natürlich hast du recht, ich dachte, der Benutzer würde einen Syntaxfehler bekommen, wie in seinem Kommentar zu der akzeptierten Antwort erwähnt, aber ich habe nicht bemerkt, dass er das Schlüsselwort "let" in seinem Kommentar verwendet. – erbth

Antwort

2

In Arrays, Bash betrachten Ausdrücke zwischen [] als Arithmetik. Also

i=2 ; f[i++]=10 

ist perfekt. Schreiben f[((i++))] ist auch korrekt, aber in diesem Fall wird nicht als der arithmetische Expansionsoperator, sondern als verschachtelte Klammern gesehen.

Beachten Sie, dass ((expr)) auswertet, dann ist es erfolgreich, wenn es wahr ist, während $((expr)) als sein Wert erweitert wird. Also f[$((i++))] ist auch richtig.

Schließlich f[$i++] ist nicht was Sie wollen, seit $i zuerst erweitert wird. Zum Beispiel wird i=j ; f[$i++] als f[j++] erweitert werden.

Bemerkung: eine seltsame Eigenschaft ist, dass bash alles, was er in der Arithmetik-Modus, ohne das $ -Zeichen kann erweitert:

$ unset i j k f 
$ i=j ; j=k ; k=5 ; f[i++]=10 
$ declare -p i j k f 
declare -- i="6" 
declare -- j="k" 
declare -- k="5" 
declare -a f='([5]="10")' 
1

Das Dollarzeichen ist in manchen Kontexten erforderlich, aber nicht die andere:

$ bash --version 
GNU bash, version 4.3.42(1)-release (x86_64-redhat-linux-gnu) 
Copyright (C) 2013 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 

$ echo ((1+2)) 
bash: syntax error near unexpected token `(' 

$ echo $((1+2)) 
3 

$ for ((x=0; x<3;++x)); do echo $x; done 
0 
1 
2 

$ for $((x=0; x<3;++x)); do echo $x; done 
bash: `$((x=0; x<3;++x))': not a valid identifier 

Nach bash man-Seite zu lesen, ist das Dollarzeichen nicht in compound commands erforderlich:

Verbindung Befehle sind die Shell-Programmierkonstrukte. Jedes Konstrukt beginnt mit einem reservierten Wort oder Steueroperator und wird durch ein entsprechendes reserviertes Wort oder einen entsprechenden Operator beendet. Alle Weiterleitungen (siehe Umleitungen), die einem zusammengesetzten Befehl zugeordnet sind, gelten für alle Befehle in diesem zusammengesetzten Befehl, sofern sie nicht ausdrücklich überschrieben werden.

In den meisten Fällen kann eine Liste von Befehlen in der Beschreibung eines Verbundbefehls durch einen oder mehrere Zeilenumbrüche vom Rest des Befehls getrennt sein, und anstelle eines Semikolons kann ein Zeilenvorschub folgen.

Bash bietet Schleifenkonstrukte, bedingte Befehle und Mechanismen zum Gruppieren von Befehlen und deren Ausführung als Einheit.

for ((expr1 ; expr2 ; expr3)) ist ein Verbindung Befehl und damit das Dollarzeichen nicht arithmetische Auswertung ermöglichen erforderlich.

Während echo $((expr)) ist kein Verbindung Befehl, weil es nicht mit einem reservierten bash Schlüsselwort beginnt, so dass es erfordert ein Dollarzeichen arithmetische Auswertung zu ermöglichen.

+0

Das ist der Punkt, den ich nicht verstehe: Warum ist das Dollarzeichen mit Echo, aber nicht in einem Array-Index erforderlich. Warum arbeiten beide Varianten in einem Array-Index? Aber ich denke, ich kann den 'for'-Fall verstehen: Ich würde sagen, das ist eine Art spezielle Syntax für das for-Schlüsselwort. Keine "reine" arithmetische Erweiterung, sondern eine spezielle For-Schleife, die aus drei arithmetischen Ausdrücken besteht. – erbth

+0

Es tut mir leid, habe es noch nicht verstanden. Warum wird das Dollarzeichen in zusammengesetzten Befehlen nicht benötigt? Warum könnte das Dollarzeichen im Befehl for() erforderlich sein, wenn es in zusammengesetzten Befehlen erforderlich ist? Gibt es eine Version des Befehls C-like for (mit 3 Teilen), der standardmäßig keine arithmetische Auswertung verwendet? Was ist mit Array-Indizes? Sind sie zusammengesetzte Befehle (vielleicht weil sie Programmierbausteine ​​sind)? – erbth