¿Hay una manera simple de revertir una matriz?
#!/bin/bash
array=(1 2 3 4 5 6 7)
echo "${array[@]}"
así que obtendría: en 7 6 5 4 3 2 1
lugar de:1 2 3 4 5 6 7
¿Hay una manera simple de revertir una matriz?
#!/bin/bash
array=(1 2 3 4 5 6 7)
echo "${array[@]}"
así que obtendría: en 7 6 5 4 3 2 1
lugar de:1 2 3 4 5 6 7
He respondido la pregunta tal como está escrita, y este código invierte la matriz. (Imprimir los elementos en orden inverso sin invertir la matriz es solo un for
ciclo de cuenta regresiva desde el último elemento a cero). Este es un algoritmo estándar de "intercambio primero y último".
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[@]}"
Funciona para matrices de longitud impar y par.
Otro enfoque poco convencional:
Salida:
Si
extdebug
está habilitado, la matrizBASH_ARGV
contiene en una función todos los parámetros posicionales en orden inverso.fuente
Enfoque no convencional (todo no puro
bash
):si todos los elementos en una matriz son solo un carácter (como en la pregunta) puede usar
rev
:de otra manera:
y si puedes usar
zsh
:fuente
tac
, como lo opuesto acat
bastante bueno para recordar, ¡GRACIAS!rev
, necesito mencionar querev
no funcionará correctamente para números con dos dígitos. Por ejemplo, un elemento de matriz de12
usar rev se imprimirá como21
. Pruébalo ;-)Si realmente quieres lo contrario en otra matriz:
Luego:
Da:
Esto debería manejar correctamente los casos en los que falta un índice de matriz, digamos que tenía
array=([1]=1 [2]=2 [4]=4)
, en cuyo caso el bucle de 0 al índice más alto puede agregar elementos adicionales vacíos.fuente
shellcheck
imprime dos advertencias:array=(1 2 3 4)
<-- SC2034: array appears unused. Verify it or export it.
y para:echo "${foo[@]}"
<-- SC2154: foo is referenced but not assigned.
declare
línea.declare -n
parece no funcionar en las versiones bash anteriores a 4.3.Para intercambiar las posiciones de la matriz en su lugar (incluso con matrices dispersas) (desde bash 3.0):
En ejecución:
Para bash más antiguo, debe usar un bucle (en bash (desde 2.04)) y usar
$a
para evitar el espacio final:Para bash desde 2.03:
Además (usando el operador de negación bit a bit) (desde bash 4.2+):
fuente
Feo, imposible de mantener, pero de una sola línea:
fuente
eval eval echo "'\"\${array[-'{1..${#array[@]}}']}\"'"
.ind=("${!array[@]}");eval eval echo "'\"\${array[ind[-'{1..${#array[@]}}']]}\"'"
Aunque no voy a decir algo nuevo y también lo usaré
tac
para revertir la matriz, creo que valdría la pena mencionar la siguiente solución de línea única con la versión bash 4.4:Pruebas:
Tenga en cuenta que el nombre de var dentro de read es el nombre de la matriz original, por lo que no se requiere una matriz auxiliar para el almacenamiento temporal.
Implementación alternativa ajustando IFS:
PD: Creo que las soluciones anteriores no funcionarán en la siguiente
bash
versión4.4
debido a la diferenteread
implementación de la función bash builtin.fuente
IFS
versión funciona sino que también está imprimiendo:declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12")
. Usando bash4.4-5
. Debes eliminar;declare -p array
al final de la primera línea, luego funciona ...declare -p
es solo una forma rápida de hacer que bash imprima la matriz real (índice y contenido). No necesita estedeclare -p
comando en su script real. Si algo sale mal en las asignaciones de sus matrices, podría terminar en un caso que${array[0]}="1 2 3 4 5 6 10 11 12"
= todos los valores almacenados en el mismo índice; usando echo no verá ninguna diferencia. Para una impresión de matriz rápida, usarádeclare -p array
le devolverá las indeces de matriz real y el valor correspondiente en cada índice.read -d'\n'
método no funcionó para ti?read -d'\n'
funciona bien.Para invertir una matriz arbitraria (que puede contener cualquier número de elementos con cualquier valor):
Con
zsh
:Con
bash
4.4+, dado que lasbash
variables no pueden contener bytes NUL de todos modos, puede usar GNUtac -s ''
en los elementos impresos como registros delimitados por NUL:POSIXly, para revertir la matriz de shell POSIX (
$@
, hecha de$1
,$2
...):fuente
Solución de golpe puro, funcionaría como una sola línea.
fuente
rev+=( "${array[i]}" )
parece más simple.también puedes considerar usar
seq
en freebsd puede omitir -1 parámetro de incremento:
fuente
Golpetazo
O
Resultado
7 6 5 4 3 2 1
Versión
fuente
tac
ya se ha mencionado: unix.stackexchange.com/a/412874/260978 , unix.stackexchange.com/a/467924/260978 , unix.stackexchange.com/a/413176/260978