Antworten:
Ich habe die Frage wie geschrieben beantwortet und dieser Code kehrt das Array um. (Das Drucken der Elemente in umgekehrter Reihenfolge, ohne das Array umzukehren, ist nur eine forSchleife, die vom letzten Element bis auf Null herunterzählt.) Dies ist ein Standardalgorithmus zum "Ersten und Letzten Tauschen".
array=(1 2 3 4 5 6 7)
min=0
max=$(( ${#array[@]} -1 ))
while [[ min -lt max ]]
do
# Swap current first and last elements
x="${array[$min]}"
array[$min]="${array[$max]}"
array[$max]="$x"
# Move closer
(( min++, max-- ))
done
echo "${array[@]}"
Es funktioniert für Arrays mit ungerader und gerader Länge.
Ein weiterer unkonventioneller Ansatz:
#!/bin/bash
array=(1 2 3 4 5 6 7)
f() { array=("${BASH_ARGV[@]}"); }
shopt -s extdebug
f "${array[@]}"
shopt -u extdebug
echo "${array[@]}"
Ausgabe:
7 6 5 4 3 2 1
Wenn extdebugaktiviert, BASH_ARGVenthält das Array in einer Funktion alle Positionsparameter in umgekehrter Reihenfolge.
Unkonventioneller Ansatz (alles nicht rein bash):
Wenn alle Elemente in einem Array nur aus einem Zeichen bestehen (wie in der Frage), können Sie Folgendes verwenden rev:
echo "${array[@]}" | revAndernfalls:
printf '%s\n' "${array[@]}" | tac | tr '\n' ' '; echound wenn du kannst zsh:
echo ${(Oa)array}tac, als das Gegenteil von catganz gut zu merken, DANKE!
rev, muss ich erwähnen, dass revfür Zahlen mit zwei Ziffern nicht richtig funktioniert. Beispielsweise wird ein Array-Element der 12 Verwendung von rev als gedruckt 21. Probieren Sie es aus ;-)
Wenn Sie tatsächlich das Gegenteil in einem anderen Array wollen:
reverse() {
# first argument is the array to reverse
# second is the output array
declare -n arr="$1" rev="$2"
for i in "${arr[@]}"
do
rev=("$i" "${rev[@]}")
done
}
Dann:
array=(1 2 3 4)
reverse array foo
echo "${foo[@]}"
Gibt:
4 3 2 1
Dies sollte Fälle korrekt behandeln, in denen beispielsweise ein Array-Index fehlt. array=([1]=1 [2]=2 [4]=4)In diesem Fall können durch Schleifen von 0 zum höchsten Index zusätzliche leere Elemente hinzugefügt werden.
shellcheckzwei Warnungen array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it.echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.
declareZeile ist.
declare -nin Bash-Versionen vor 4.3 nicht funktioniert.
So tauschen Sie die Array-Positionen aus (auch bei spärlichen Arrays) (seit Bash 3.0):
#!/bin/bash
# Declare an sparse array to test:
array=([5]=101 [6]=202 [10]=303 [11]=404 [20]=505 [21]=606 [40]=707)
echo "Initial array values"
declare -p array
swaparray(){ local temp; temp="${array[$1]}"
array[$1]="${array[$2]}"
array[$2]="$temp"
}
ind=("${!array[@]}") # non-sparse array of indexes.
min=-1; max="${#ind[@]}" # limits to one before real limits.
while [[ min++ -lt max-- ]] # move closer on each loop.
do
swaparray "${ind[min]}" "${ind[max]}" # Exchange first and last
done
echo "Final Array swapped in place"
declare -p array
echo "Final Array values"
echo "${array[@]}"
Bei der Ausführung:
./script
Initial array values
declare -a array=([5]="101" [6]="202" [10]="303" [11]="404" [20]="505" [21]="606" [40]="707")
Final Array swapped in place
declare -a array=([5]="707" [6]="606" [10]="505" [11]="404" [20]="303" [21]="202" [40]="101")
Final Array values
707 606 505 404 303 202 101
Für ältere Bashs müssen Sie eine Schleife (in Bash (seit 2.04)) verwenden und $adas folgende Leerzeichen verwenden , um das nachfolgende Leerzeichen zu vermeiden:
#!/bin/bash
array=(101 202 303 404 505 606 707)
last=${#array[@]}
a=""
for (( i=last-1 ; i>=0 ; i-- ));do
printf '%s%s' "$a" "${array[i]}"
a=" "
done
echo
Für Bash seit 2.03:
#!/bin/bash
array=(101 202 303 404 505 606 707)
last=${#array[@]}
a="";i=0
while [[ last -ge $((i+=1)) ]]; do
printf '%s%s' "$a" "${array[ last-i ]}"
a=" "
done
echo
Auch (mit dem bitweisen Negationsoperator) (seit Bash 4.2+):
#!/bin/bash
array=(101 202 303 404 505 606 707)
last=${#array[@]}
a=""
for (( i=0 ; i<last ; i++ )); do
printf '%s%s' "$a" "${array[~i]}"
a=" "
done
echo
Hässlich, nicht zu pflegen, aber Einzeiler:
eval eval echo "'\"\${array['{$((${#array[@]}-1))..0}']}\"'"
eval eval echo "'\"\${array[-'{1..${#array[@]}}']}\"'".
ind=("${!array[@]}");eval eval echo "'\"\${array[ind[-'{1..${#array[@]}}']]}\"'"
Obwohl ich nichts Neues erzählen werde und auch tacdas Array umkehren werde, wäre es dennoch erwähnenswert, die folgende einzeilige Lösung mit der bash-Version 4.4 zu erwähnen:
$ read -d'\n' -a array < <(printf '%s\n' "${array[@]}" |tac)
Testen:
$ array=(1 2 3 4 5 6 10 11 12)
$ echo "${array[@]}"
1 2 3 4 5 6 10 11 12
$ read -d'\n' -a array < <(printf '%s\n' "${array[@]}"|tac)
$ echo "${array[@]}"
12 11 10 6 5 4 3 2 1
Beachten Sie, dass der in read enthaltene Variablenname der Name des ursprünglichen Arrays ist, sodass für die temporäre Speicherung kein Hilfsarray erforderlich ist.
Alternative Implementierung durch Anpassung des IFS:
$ IFS=$'\n' read -d '' -a array < <(printf '%s\n' "${array[@]}"|tac);declare -p array
declare -a array=([0]="12" [1]="11" [2]="10" [3]="6" [4]="5" [5]="4" [6]="3" [7]="2" [8]="1")
PS: Ich denke, obige Lösungen funktionieren nicht in der folgenden bashVersion, 4.4da verschiedene readBash-Funktionen implementiert wurden.
IFSVersion funktioniert , aber es ist auch Druck: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Bash benutzen 4.4-5. Sie haben zu entfernen , ;declare -p arrayam Ende der ersten Zeile, dann funktioniert es ...
declare -pist nur ein schneller Weg, um bash das echte Array (Index und Inhalt) drucken zu lassen. Sie brauchen diesen declare -pBefehl nicht in Ihrem echten Skript. Wenn in Ihren Array-Zuweisungen etwas schief geht, kann dies dazu führen, dass ${array[0]}="1 2 3 4 5 6 10 11 12"= alle Werte im selben Index gespeichert sind - mit Echo werden Sie keinen Unterschied feststellen. Für einen schnellen Array-Ausdruck erhalten declare -p arraySie mit die tatsächlichen Array-Indices und den entsprechenden Wert in jedem Index.
read -d'\n'Methode bei dir nicht funktioniert?
read -d'\n'funktioniert gut.
So kehren Sie ein beliebiges Array um (das beliebig viele Elemente mit beliebigen Werten enthalten kann):
Mit zsh:
array_reversed=("${(@Oa)array}")
Mit bash4.4+, da bashVariablen nicht enthalten NUL - Bytes wie auch immer, Sie GNU verwenden können , tac -s ''auf die Elemente gedruckt als NUL Datensätze begrenzt:
readarray -td '' array_reversed < <(
((${#array[@]})) && printf '%s\0' "${array[@]}" | tac -s '')
POSIXly, um das POSIX-Shell-Array ( $@, aus $1, $2...) umzukehren :
code='set --'
n=$#
while [ "$n" -gt 0 ]; do
code="$code \"\${$n}\""
n=$((n - 1))
done
eval "$code"
Reine bash Lösung, würde als Einzeiler funktionieren.
$: for (( i=${#array[@]}-1; i>=0; i-- ))
> do rev[${#rev[@]}]=${array[i]}
> done
$: echo "${rev[@]}"
7 6 5 4 3 2 1
rev+=( "${array[i]}" )scheint einfacher zu sein.
Sie können auch in Betracht ziehen, seq
array=(1 2 3 4 5 6 7)
for i in $(seq $((${#array[@]} - 1)) -1 0); do
echo ${array[$i]}
done
In freebsd können Sie den Inkrement-Parameter -1 weglassen:
for i in $(seq $((${#array[@]} - 1)) 0); do
echo ${array[$i]}
done
array=(1 2 3 4 5 6 7)
echo "${array[@]} " | tac -s ' '
Oder
array=(1 2 3 4 5 6 7)
reverse=$(echo "${array[@]} " | tac -s ' ')
echo ${reverse[@]}
7 6 5 4 3 2 1
$ tac --version
tac (GNU coreutils) 8.28
tacwurde bereits erwähnt: unix.stackexchange.com/a/412874/260978 , unix.stackexchange.com/a/467924/260978 , unix.stackexchange.com/a/413176/260978