Zugriff auf die Array-Indexvariable über die Bash-Shell-Skriptschleife?

18

Ich möchte auf die Array-Indexvariable zugreifen, während ich ein Array in meinem Bash-Shell-Skript durchschleife.

myscript.sh
#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in ${AR[*]}; do
  echo $i
done

Das Ergebnis des obigen Skripts ist:

foo
bar
baz
bat

Das Ergebnis, das ich suche, ist:

0
1
2
3

Wie ändere ich mein Skript, um dies zu erreichen?

Mäher
quelle
6
Beachten Sie auch , dass man im Grunde nie wollen "${array[*]}"statt "${array[@]}". Wenn Sie *anstelle von " @more" oder "less" verwenden, wird dies als Zeichenfolge anstelle eines Arrays behandelt.
Jordanien

Antworten:

23

Sie können dies mithilfe der Liste der Array-Schlüssel tun . Von der bashManpage:

${!name[@]}
${!name[*]}

Liste der Array-Schlüssel . Wenn name eine Arrayvariable ist, wird die Liste der im Namen zugewiesenen Arrayindizes (Schlüssel) erweitert. Wenn name kein Array ist, wird es auf " 0name" und ansonsten auf "null" erweitert. Wenn @verwendet und die Erweiterung in doppelten Anführungszeichen angezeigt wird, wird jede Taste zu einem separaten Wort erweitert.

Für Ihr Beispiel:

#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in "${!AR[@]}"; do
  printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done

Das führt zu:

${AR[0]}=foo
${AR[1]}=bar
${AR[2]}=baz
${AR[3]}=bat

Beachten Sie, dass dies auch für nicht aufeinanderfolgende Indizes funktioniert:

#!/bin/bash
AR=([3]='foo' [5]='bar' [25]='baz' [7]='bat')
for i in "${!AR[@]}"; do
  printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done

Das führt zu:

${AR[3]}=foo
${AR[5]}=bar
${AR[7]}=bat
${AR[25]}=baz
Jordanien
quelle
1
Obwohl diese Antwort das gewünschte Ergebnis erzielt, wird sie durch die printf-Anweisung unnötig verschleiert. Zum Beispiel: printf "$i=(${AR[i]})\n"oder echo "$i=(${ARi]})"beide geben ein kleines Extra, indem sie zeigen, wie man key & var bekommt, aber genau genommen echo "$i"hätte das OP beantwortet. Der Rest ist "bash fu" :)
Dimmech
6

Zusätzlich zu jordanms Antwort können Sie auch eine Cähnliche Schleife in bash:

for ((idx=0; idx<${#array[@]}; ++idx)); do
    echo "$idx" "${array[idx]}"
done
pfnuesel
quelle
1

Sie können so etwas tun:

#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
length=${#AR[@]}
for (( i = 0; i < length; i++ )); do
  echo "$i"
done

Ausgabe:

0
1
2
3
F.9876
quelle
1
Was sagt das, was  Pfnüsels Antwort   noch nicht sagt?
G-Man sagt, dass Monica
Ich kann mich irren, aber bewertet die Antwort von Pfnuesels die Array-Länge nicht bei jeder Iteration neu?
Chris