tutorial traduccion script comandos bash

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