Yanıtlar:
Soruyu yazılı olarak yanıtladım ve bu kod diziyi tersine çevirir. (Diziyi tersine çevirmeden öğeleri ters sırada yazdırmak, yalnızca forson öğeden sıfıra geri sayım yapan bir döngüdür.) Bu standart bir "ilk ve son değiştirme" algoritmasıdır.
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[@]}"
Tek ve eşit uzunlukta diziler için çalışır.
Başka bir alışılmadık yaklaşım:
#!/bin/bash
array=(1 2 3 4 5 6 7)
f() { array=("${BASH_ARGV[@]}"); }
shopt -s extdebug
f "${array[@]}"
shopt -u extdebug
echo "${array[@]}"
Çıktı:
7 6 5 4 3 2 1
Eğer extdebugetkinleştirildiğinde, dizi BASH_ARGVters sırada tüm konumsal parametreler işlevde içerir.
Alışılmadık yaklaşım (hepsi saf değil bash):
bir dizideki tüm öğeler yalnızca bir karakterse (sorudaki gibi) kullanabilirsiniz rev:
echo "${array[@]}" | revaksi takdirde:
printf '%s\n' "${array[@]}" | tac | tr '\n' ' '; echove eğer kullanabiliyorsanız zsh:
echo ${(Oa)array}tactersi olarak, cat, TEŞEKKÜRLER hatırlamak oldukça iyi!
revbahsetmek gerekir rev. Örneğin 12 rev kullanımının bir dizi öğesi olarak yazdırılacaktır 21. Bir deneyin ;-)
Aslında tersi başka bir dizide istiyorsanız:
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
}
Sonra:
array=(1 2 3 4)
reverse array foo
echo "${foo[@]}"
verir:
4 3 2 1
Bu, bir dizi dizininin eksik olduğu durumları, örneğin array=([1]=1 [2]=2 [4]=4)0'dan en yüksek dizine döngü yapmak ek, boş, elemanlar ekleyebilir.
shellcheckiki uyarı yazdırıyor: array=(1 2 3 4) <-- SC2034: array appears unused. Verify it or export it.ve bunun için:echo "${foo[@]}" <-- SC2154: foo is referenced but not assigned.
declarehat bunun için.
declare -n4.3'ten önceki bash sürümlerinde işe yaramadığını unutmayın .
Dizi konumlarını yerinde değiştirmek için (seyrek dizilerle bile) (bash 3.0'dan beri):
#!/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[@]}"
Yürütme sırasında:
./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
Eski bash için, bir döngü (bash (2.04'ten beri)) kullanmanız $ave arka boşluktan kaçınmak için kullanmanız gerekir:
#!/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
2.03'ten beri bash için:
#!/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
Ayrıca (bitsel olumsuzlama operatörünü kullanarak) (bash 4.2+'den beri):
#!/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
Çirkin, sürdürülemez, ancak bir astar:
eval eval echo "'\"\${array['{$((${#array[@]}-1))..0}']}\"'"
eval eval echo "'\"\${array[-'{1..${#array[@]}}']}\"'".
ind=("${!array[@]}");eval eval echo "'\"\${array[ind[-'{1..${#array[@]}}']]}\"'"
Yeni bir şey anlatmayacağım ve ben de tacdiziyi tersine çevirmek için kullanacak olsa da, ben bash 4.4 sürümünü kullanarak feryat tek satır çözüm bahsetmeye layık olsa da:
$ read -d'\n' -a array < <(printf '%s\n' "${array[@]}" |tac)
Test yapmak:
$ 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
Okuma içindeki var adının orijinal dizi olarak ad olduğunu unutmayın, bu nedenle geçici depolama için yardımcı dizi gerekmez.
IFS'yi ayarlayarak alternatif uygulama:
$ 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")
Not: Yukarıdaki çözümlerin farklı bash yerleşik işlev uygulaması nedeniyle bashferyat versiyonunda çalışmayacağını düşünüyorum .4.4read
IFSVersiyon çalışıyor ama o da yazdırıyor: declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12"). Bash kullanma 4.4-5. ;declare -p arrayİlk satırın sonunda kaldırmanız gerekiyor , o zaman işe yarıyor ...
declare -p, bash baskısını gerçek dizi (dizin ve içerik) yapmanın hızlı bir yoludur. declare -pGerçek komut dosyanızda bu komuta ihtiyacınız yoktur . Dizilerinizin atamalarında bir şeyler ters giderse ${array[0]}="1 2 3 4 5 6 10 11 12", aynı dizinde depolanan tüm değerlerin = yankı kullanarak bir fark görmeyeceksiniz. Hızlı bir dizi çıktısı için declare -p array, kullanarak gerçek dizi indeksleri ve her dizindeki karşılık gelen değer döndürülür.
read -d'\n'yöntem sizin için işe yaramadı mı?
read -d'\n'iyi çalışıyor.
Rasgele bir diziyi tersine çevirmek için (herhangi bir değere sahip çok sayıda öğe içerebilir):
İle zsh:
array_reversed=("${(@Oa)array}")
İle bash4.4+, göz önüne alındığında bashdeğişkenler GNU'yu kullanabilirsiniz, NUL zaten bayt içeremez tac -s ''NUL kayıtlarını ayrılmış olarak basılmış elemanlarında:
readarray -td '' array_reversed < <(
((${#array[@]})) && printf '%s\0' "${array[@]}" | tac -s '')
POSIXly, POSIX kabuk dizisini tersine çevirmek için ( $@, yapılmış $1, $2...):
code='set --'
n=$#
while [ "$n" -gt 0 ]; do
code="$code \"\${$n}\""
n=$((n - 1))
done
eval "$code"
Saf bash çözümü, tek astar olarak çalışır.
$: 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]}" )daha basit görünüyor.
ayrıca kullanmayı düşünebilirsiniz seq
array=(1 2 3 4 5 6 7)
for i in $(seq $((${#array[@]} - 1)) -1 0); do
echo ${array[$i]}
done
freebsd'de -1 artış parametresini atlayabilirsiniz:
for i in $(seq $((${#array[@]} - 1)) 0); do
echo ${array[$i]}
done
array=(1 2 3 4 5 6 7)
echo "${array[@]} " | tac -s ' '
Veya
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
taczaten belirtilmişti: unix.stackexchange.com/a/412874/260978 , unix.stackexchange.com/a/467924/260978 , unix.stackexchange.com/a/413176/260978