traduccion - ¿Cómo invertir la matriz en bash onliner FOR loop?
bash ubuntu (6)
¿Cómo puedo invertir el orden en que realizo un bucle for para una matriz definida?
Para iterar a través de la matriz estoy haciendo esto:
$ export MYARRAY=("one" "two" "three" "four")
$ for i in ${MYARRAY[@]}; do echo $i;done
one
two
three
four
¿Hay una función en la que puedo invertir el orden de la matriz?
Uno de los pensamientos que tuve fue generar una secuencia de índices invertidos y llamar a los elementos utilizando este índice invertido, pero tal vez haya una alternativa más rápida, o al menos más fácil de leer.
Puedes usar tac , que es lo contrario de cat
en el sentido de que invierte las líneas.
MYARRAY=("one" "two" "three" "four")
for item in "$MYARRAY"; do
echo "$item";
done | tac
# four
# three
# two
# one
Puedes usar el estilo C para el bucle:
for (( idx=${#MYARRAY[@]}-1 ; idx>=0 ; idx-- )) ; do
echo "${MYARRAY[idx]}"
done
Para una matriz con "agujeros", el número de elementos ${#arr[@]}
no corresponde al índice del último elemento. Puede crear otra serie de índices y caminar hacia atrás de la misma manera:
#! /bin/bash
arr[2]=a
arr[7]=b
echo ${#arr[@]} # only 2!!
indices=( ${!arr[@]} )
for ((i=${#indices[@]} - 1; i >= 0; i--)) ; do
echo "${arr[indices[i]]}"
done
Qué tal esto:
for i in `printf ''%s/n'' "${MYARRAY[@]}"|tac`; do echo $i; done
La salida es:
four
three
two
one
Limitación: no funciona si la matriz contiene nuevas líneas. Como solución puede implementar la función:
reverse(){ reversed=();local i;for ((i=$#;i>0;i--)); do reversed+=("${!i}");done; }
y úsalo de esta manera:
reverse "${MYARRAY[@]}" && for i in "${reversed[@]}"; do echo $i; done
Si está hablando de una matriz numérica secuencial (por ejemplo, para eliminar el historial de bash), puede enumerar esto en orden inverso, por ejemplo:
for i in {16..10}; do history -d $i; done
Me doy cuenta de que este es un tema fuera de tema y me disculpo por eso, sin embargo, pensé que probablemente valdría la pena mencionarlo.
Simple como una cuerda:
% unset c; a="1 2 3 4 5"; for b in $a; do c="$b $c"; done; echo $c
5 4 3 2 1
¿Seguro que quieres sintaxis de matriz ??:
% unset c; declare -a c; a=(1 2 3 4 5); i=0; for b in ${a[*]}; /
do c[$((${#a[@]}-$i))]=$b; i=$(($i+1)); done; echo ${c[*]}
5 4 3 2 1
_arr+=( ''"${_arrev} is an actual "${array[@]}"'' ) ⏎
_arr+=( ''"${_arrev} is created as a result"'' )
_arr+=( ''"of reversing the key order in"'' )
_arr+=( ''"this "${_arr}. It handles zsh and"'' )
_arr+=( ''"bash arrays intelligently by tracking"'' )
_arr+=( ''"shell "$ENV." quotes=fine ( i hope ) "'' )
. <<REVERSE /dev/stdin ⏎
_arrev=( $(: $((l=${#_arr[@]}${ZSH_VERSION++1})) ; printf ''"${_arr[$((''$l''-%d))]}" '' `seq 1 $l`) )
REVERSE
echo ; printf %s//n ${_arrev}
"shell "$ENV." quotes=fine ( i hope ) "
"bash arrays intelligently by tracking"
"this "${_arr}. It handles zsh and"
"of reversing the key order in"
"${_arrev} is created as a result"
"${_arrev} is an actual "${array[@]}"
Esto debería manejar cualquier posible conjunto, creo.
Si está interesado en lo que está sucediendo allí, le sugiero que mire primero here . Entonces quizás here , definitivamente here , y, si tienes tiempo, here y here .
En todas esas respuestas, discuto diferentes aspectos del documento aquí (y en muchos otros) que puede utilizar para su ventaja. Por ejemplo, discuto dos veces las variables de evaluación, que se realizan arriba, y en una declaración declaramos una función que declara globalmente otra función llamada "_$1"
en solo 5 o 6 líneas, la mayoría de las cuales era _$1() { func body ; }
_$1() { func body ; }
. Es bastante útil si lo usas correctamente.
Con respecto al cambio automático entre bash/zsh,
bueno bash/zsh,
eso es otra cosa, pero también muy simple. Ver here