Czy istnieje prosty sposób na odwrócenie tablicy?
#!/bin/bash
array=(1 2 3 4 5 6 7)
echo "${array[@]}"
więc otrzymałbym: 7 6 5 4 3 2 1
zamiast:1 2 3 4 5 6 7
Czy istnieje prosty sposób na odwrócenie tablicy?
#!/bin/bash
array=(1 2 3 4 5 6 7)
echo "${array[@]}"
więc otrzymałbym: 7 6 5 4 3 2 1
zamiast:1 2 3 4 5 6 7
Odpowiedziałem na pytanie, jak napisano, a ten kod odwraca tablicę. (Drukowanie elementów w odwrotnej kolejności bez odwracania tablicy to tylko for
pętla odliczająca od ostatniego elementu do zera.) Jest to standardowy algorytm „zamień pierwszy i ostatni”.
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[@]}"
Działa dla tablic o nieparzystej i parzystej długości.
Kolejne niekonwencjonalne podejście:
Wynik:
Jeśli
extdebug
jest włączone, tablicaBASH_ARGV
zawiera w funkcji wszystkie parametry pozycyjne w odwrotnej kolejności.źródło
Niekonwencjonalne podejście (wszystkie nie są czyste
bash
):jeśli wszystkie elementy w tablicy są tylko jednym znakiem (jak w pytaniu), możesz użyć
rev
:Inaczej:
a jeśli możesz użyć
zsh
:źródło
tac
, jako przeciwieństwocat
całkiem dobrego do zapamiętania, DZIĘKI!rev
, muszę wspomnieć, żerev
nie będzie działać poprawnie dla liczb z dwiema cyframi. Na przykład element tablicy12
wykorzystujący rev zostanie wydrukowany jako21
. Spróbuj ;-)Jeśli faktycznie chcesz odwrócić w innej tablicy:
Następnie:
Daje:
Powinno to poprawnie obsługiwać przypadki, w których brakuje indeksu tablicowego, powiedzmy, że miałeś
array=([1]=1 [2]=2 [4]=4)
, w którym to przypadku zapętlenie od 0 do najwyższego indeksu może dodawać dodatkowe, puste elementy.źródło
shellcheck
drukuje dwa ostrzeżenia:array=(1 2 3 4)
<-- SC2034: array appears unused. Verify it or export it.
i dla:echo "${foo[@]}"
<-- SC2154: foo is referenced but not assigned.
declare
jest linia.declare -n
wydaje się , że nie działa w wersjach bash przed 4.3.Aby zamienić pozycje tablic na miejscu (nawet przy rzadkich tablicach) (od wersji bash 3.0):
Po wykonaniu:
W przypadku starszej wersji bash musisz użyć pętli (w wersji bash (od 2.04)) i użyć,
$a
aby uniknąć końcowego miejsca:Dla bash od 2.03:
Również (używając bitowego operatora negacji) (od bash 4.2+):
źródło
Brzydki, niemożliwy do utrzymania, ale jednowarstwowy:
źródło
eval eval echo "'\"\${array[-'{1..${#array[@]}}']}\"'"
.ind=("${!array[@]}");eval eval echo "'\"\${array[ind[-'{1..${#array[@]}}']]}\"'"
Chociaż nie powiem nic nowego i użyję również
tac
do odwrócenia tablicy, ale warto wspomnieć o rozwiązaniu jednowierszowym przy użyciu wersji bash 4.4:Testowanie:
Pamiętaj, że nazwa var wewnątrz odczytu jest nazwą oryginalnej tablicy, więc nie jest wymagana tablica pomocnicza do przechowywania w temp.
Alternatywne wdrożenie poprzez dostosowanie IFS:
PS: Myślę, że powyższe rozwiązania nie będą działać w
bash
poniższej wersji z4.4
powodu różnychread
implementacji wbudowanych funkcji bash.źródło
IFS
Wersja działa, ale także drukowania:declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12")
. Korzystanie z bash4.4-5
. Musisz usunąć;declare -p array
na końcu pierwszego wiersza, a następniedeclare -p
to tylko szybki sposób, aby bash wydrukował prawdziwą tablicę (indeks i zawartość). Nie potrzebujesz tegodeclare -p
polecenia w swoim prawdziwym skrypcie. Jeśli coś pójdzie nie tak z przypisaniami tablic, możesz skończyć w przypadku, że${array[0]}="1 2 3 4 5 6 10 11 12"
= wszystkie wartości zapisane w tym samym indeksie - używając echa nie zobaczysz żadnej różnicy. W przypadku szybkiego wydruku tablic użyciedeclare -p array
zwróci rzeczywiste indeksy tablic i odpowiednią wartość w każdym indeksie.read -d'\n'
metoda nie działała dla Ciebie?read -d'\n'
działa w porządku.Aby odwrócić dowolną tablicę (która może zawierać dowolną liczbę elementów o dowolnych wartościach):
Z
zsh
:W wersji
bash
4.4+, biorąc pod uwagę, żebash
zmienne i tak nie mogą zawierać bajtów NUL, możesz używać GNUtac -s ''
na elementach drukowanych jako rekordy rozdzielane NUL:POSIXly, aby odwrócić tablicę POSIX powłoki (
$@
, wykonaną z$1
,$2
...)źródło
Rozwiązanie Pure Bash działałoby jako jedno-liniowy.
źródło
rev+=( "${array[i]}" )
wydaje się prostsze.możesz również rozważyć użycie
seq
we Freebsd możesz pominąć parametr przyrostu -1:
źródło
Grzmotnąć
Lub
Wynik
7 6 5 4 3 2 1
Wersja
źródło
tac
był już wspomniany: unix.stackexchange.com/a/412874/260978 , unix.stackexchange.com/a/467924/260978 , unix.stackexchange.com/a/413176/260978