Nos sistemas GNU, o contrário de cat é tac:
$ tac -s" " <<< "$VAR " # Please note the added final space.
100 90 80 70 60 50 40 30 20 10
Então, se eu tenho uma variável
VAR='10 20 30 40 50 60 70 80 90 100'
e ecoar para fora
echo "$VAR"
10 20 30 40 50 60 70 80 90 100
No entanto, mais abaixo no script, eu preciso inverter a ordem dessa variável para que ela seja exibida como
echo "$VAR" | <code to reverse it>
100 90 80 70 60 50 40 30 20 10
Eu tentei usar rev e literalmente invertei tudo, então saiu como
echo "$VAR" | rev
001 09 08 07 06 05 04 03 02 01
Para uma lista pequena e em uma variável, o próprio shell é a solução mais 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
Saída:
100 90 80 70 60 50 40 30 20 10
Nota: a operação de divisão em set -- $var
é segura para a string exata usada aqui, mas não será assim se a string contiver caracteres curinga ( *
, ?
ou []
). Isso pode ser evitado com set -f
antes da divisão, se necessário.
A mesma nota também é válida para as soluções a seguir (exceto onde indicado).
Ou, se você quiser definir outra variável com a 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"
Ou usando apenas os parâmetros posicionais.
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"
Ou usando apenas uma variável (que pode ser var em si):
Nota: Esta solução não é afetada pela globalização nem pelo IFS.
var="10 20 30 40 50 60 70 80 90 100"
a=" $var"
while [[ $a ]]; do
printf '<%s>' "${a##* }"
var="${a% *}"
done
awk
para o resgate
$ 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
com perl
, cortesia Como ler um endereço IP para trás? compartilhado por @steeldriver
$ echo "$var" | perl -lane '$,=" "; print reverse @F'
100 90 80 70 60 50 40 30 20 10
Ou, com bash
convertendo a string em array
$ 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
Você pode usar recursos bash, como arrays, para fazer isso totalmente em processo:
#!/bin/bash
VAR="10 20 30 40 50 60 70 80 90 100"
a=($VAR); rev_a=()
for ((i=${#a[@]}-1;i>=0;i--)); do rev_a+=( ${a[$i]} ); done;
RVAR=${rev_a[*]};
Esta deve ser a maneira mais rápida de fazer isso, desde que $ VAR não seja muito grande.
printf "%s\n" $var | tac | paste -sd' '
100 90 80 70 60 50 40 30 20 10
Use um pouco da mágica do Python aqui:
bash-4.3$ VAR='10 20 30 40 50 60 70 80 90 100'
bash-4.3$ python -c 'import sys;print " ".join(sys.argv[1].split()[::-1])' "$VAR"
100 90 80 70 60 50 40 30 20 10
A maneira como isso funciona é bastante simples:
"$VAR"
como segunda linha de comando paramenter sys.argv[1]
(primeiro parâmetro com -c
opção é sempre apenas isso - -c
. Observe a citação em torno de "$VAR"
para evitar dividir a própria variável em individual palavras (o que ele fez por shell, não por python) .split()
para dividi-lo em uma lista de strings [::-1]
part é apenas sintaxe de fatia estendida para obter o reverso da lista " ".join()
e imprimimos Mas aqueles que não são grandes fãs de Python, poderíamos usar AWK
para fazer essencialmente a mesma coisa: dividir e imprimir matriz inversa:
echo "$VAR" | awk '{split($0,a);x=length(a);while(x>-1){printf "%s ",a[x];x--};print ""}'
100 90 80 70 60 50 40 30 20 10
zsh
:
print -r -- ${(Oa)=VAR}
$=VAR
divide $VAR
em $IFS
. (Oa)
ordena a lista resultante na ordem inversa da matriz. print -r --
(como em ksh
), igual a echo -E -
( zsh
specific) é uma versão confiável de echo
: exibe seus argumentos como -é separado por espaço, terminado por nova linha.
Se você quiser dividir apenas no espaço, e não no que for que $IFS
contém (espaço, tabulação, nova linha, nul por padrão), atribua espaço a $IFS
ou use uma divisão explícita como:
print -r -- ${(Oas: :)VAR}
Para ordenar por ordem numérica inversa:
$ 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 (assim também funcionaria com bash
):
Com mecanismos internos de shell (exceto para printf
em alguns shells) somente (melhor para variáveis com um valor curto):
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"
Com awk
(melhor para grandes variáveis, especialmente com bash
, mas até o limite do tamanho dos argumentos (ou de um único argumento)):
awk '
BEGIN {
n = split(ARGV[1], a);
while (n) {printf "%s", sep a[n--]; sep = " "}
print ""
}' "$VAR"
Ferramentas de software inelegant POSIX :
echo 'echo $VAR | tr ' ' '\n' | sort -nr'