
Entonces si tengo una variable
VAR='10 20 30 40 50 60 70 80 90 100'
y resuélvelo
echo "$VAR"
10 20 30 40 50 60 70 80 90 100
Sin embargo, más abajo en el script necesito invertir el orden de esta variable para que se muestre como algo así como
echo "$VAR" | <code to reverse it>
100 90 80 70 60 50 40 30 20 10
Intenté usar rev y literalmente invirtió todo, por lo que salió como
echo "$VAR" | rev
001 09 08 07 06 05 04 03 02 01
Respuesta1
En los sistemas GNU, el reverso de cat es tac:
$ tac -s" " <<< "$VAR " # Please note the added final space.
100 90 80 70 60 50 40 30 20 10
Respuesta2
Para una lista corta, y en una variable, el propio shell es la solución más rápida:
var="10 20 30 40 50 60 70 80 90 100"
set -- $var; unset a
for ((i=$#;i>0;i--)); do
printf '%s%s' "${a:+ }" "${!i}"
a=1
done
echo
Producción:
100 90 80 70 60 50 40 30 20 10
Nota: la operación de división set -- $var
es segura para la cadena exacta utilizada aquí, pero no lo será si la cadena contiene caracteres comodín ( *
o ?
) []
. Puede evitarse set -f
antes de la división, si es necesario. La misma nota también es válida para las siguientes soluciones (excepto donde se indique lo contrario).
O, si desea configurar alguna otra variable con la lista inversa:
var="10 20 30 40 50 60 70 80 90 100"
set -- $var
for i; do out="$i${out:+ }$out"; done
echo "$out"
O usando solo los parámetros posicionales.
var="10 20 30 40 50 60 70 80 90 100"
set -- $var
a=''
for i
do set -- "$i${a:+ $@}"
a=1
done
echo "$1"
O usar solo una variable (que puede ser la propia var):
Nota: Esta solución no se ve afectada por globing ni IFS.
var="10 20 30 40 50 60 70 80 90 100"
a=" $var"
while [[ $a ]]; do
printf '<%s>' "${a##* }"
var="${a% *}"
done
Respuesta3
awk
al rescate
$ var='10 20 30 40 50 60 70 80 90 100'
$ echo "$var" | awk '{for(i=NF; i>0; i--) printf i==1 ? $i"\n" : $i" "}'
100 90 80 70 60 50 40 30 20 10
con perl
cortesía¿Cómo leer una dirección IP al revés?compartido por @steeldriver
$ echo "$var" | perl -lane '$,=" "; print reverse @F'
100 90 80 70 60 50 40 30 20 10
O consigo bash
mismo convirtiendo la cadena en una matriz
$ arr=($var)
$ for ((i=${#arr[@]}-1; i>=0; i--)); do printf "${arr[i]} "; done; echo
100 90 80 70 60 50 40 30 20 10
Respuesta4
zsh
:
print -r -- ${(Oa)=VAR}
$=VAR
se divide $VAR
en $IFS
. (Oa)
ordena la lista resultante en orden inverso. print -r --
(como en ksh
), igual que echo -E -
( zsh
específico) esversiones confiables deecho
: imprime sus argumentos tal cual, separados por espacios, terminados por una nueva línea.
Si desea dividir solo en el espacio, y no en lo que $IFS
contiene (espacio, tabulación, nueva línea, nulo de forma predeterminada), asigne espacio $IFS
o use una división explícita como:
print -r -- ${(Oas: :)VAR}
Para ordenar en orden numérico inverso:
$ VAR='50 10 20 90 100 30 60 40 70 80'
$ print -r -- ${(nOn)=VAR}
100 90 80 70 60 50 40 30 20 10
POSIXly (también funcionaría con bash
):
Solo con mecanismos integrados en el shell (excepto printf
en algunos shells) (mejor para variables con un valor corto):
unset -v IFS # restore IFS to its default value of spc, tab, nl
set -o noglob # disable glob
set -- $VAR # use the split+glob operator to assign the words to $1, $2...
reversed_VAR= sep=
for i do
reversed_VAR=$i$sep$reversed_VAR
sep=' '
done
printf '%s\n' "$reversed_VAR"
Con awk
(mejor para variables grandes, especialmente con bash
, pero hasta el límite del tamaño de los argumentos (o de un solo argumento)):
awk '
BEGIN {
n = split(ARGV[1], a);
while (n) {printf "%s", sep a[n--]; sep = " "}
print ""
}' "$VAR"