Existe uma maneira simples de reverter uma matriz?
#!/bin/bash
array=(1 2 3 4 5 6 7)
echo "${array[@]}"
então eu receberia: em 7 6 5 4 3 2 1
vez de:1 2 3 4 5 6 7
bash
shell-script
array
bash-array
nath
fonte
fonte
Outra abordagem não convencional:
Resultado:
Se
extdebug
ativado, o arrayBASH_ARGV
contém em uma função todos os parâmetros posicionais na ordem inversa.fonte
Abordagem não convencional (nem tudo pura
bash
):se todos os elementos em uma matriz tiverem apenas um caractere (como na pergunta), você poderá usar
rev
:de outra forma:
e se você pode usar
zsh
:fonte
tac
, como o oposto decat
muito bom para lembrar, OBRIGADO!rev
, preciso mencionar querev
não funcionará corretamente para números com dois dígitos. Por exemplo, um elemento da matriz do12
uso de rev será impresso como21
. Faça uma tentativa ;-) #Se você realmente deseja o inverso em outra matriz:
Então:
Dá:
Isso deve tratar corretamente os casos em que um índice de matriz está ausente, digamos que você tenha
array=([1]=1 [2]=2 [4]=4)
, nesse caso, o loop de 0 ao índice mais alto pode adicionar elementos vazios adicionais.fonte
shellcheck
imprima dois avisos:array=(1 2 3 4)
<-- SC2034: array appears unused. Verify it or export it.
e por:echo "${foo[@]}"
<-- SC2154: foo is referenced but not assigned.
declare
serve a linha.declare -n
parece não funcionar nas versões bash anteriores ao 4.3.Para trocar as posições da matriz no local (mesmo com matrizes esparsas) (desde o bash 3.0):
Na execução:
Para o bash mais antigo, você precisa usar um loop (no bash (desde 2.04)) e usá-lo
$a
para evitar o espaço à direita:Para o bash desde a versão 2.03:
Também (usando o operador de negação bit a bit) (desde o bash 4.2+):
fonte
Feio, insustentável, mas com uma linha:
fonte
eval eval echo "'\"\${array[-'{1..${#array[@]}}']}\"'"
.ind=("${!array[@]}");eval eval echo "'\"\${array[ind[-'{1..${#array[@]}}']]}\"'"
Embora eu não vou contar algo novo e também usarei
tac
para reverter a matriz, vale a pena mencionar a solução de linha única abaixo usando a versão 4.4 do bash:Teste:
Lembre-se de que o nome var dentro da leitura é o nome da matriz original, portanto, nenhuma matriz auxiliar é necessária para o armazenamento temporário.
Implementação alternativa ajustando o IFS:
PS: Eu acho que as soluções acima não funcionarão na
bash
versão abaixo4.4
devido àread
implementação de funções diferentes do bash.fonte
IFS
versão funciona, mas ele também está imprimindo:declare -a array=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="10" [7]="11" [8]="12")
. Usando o bash4.4-5
. Você tem que remover;declare -p array
no final da primeira linha, em seguida, ele funciona ...declare -p
é apenas uma maneira rápida de fazer com que o bash imprima a matriz real (índice e conteúdo). Você não precisa destedeclare -p
comando em seu script real. Se algo der errado nas atribuições de suas matrizes, você poderá terminar em um caso que${array[0]}="1 2 3 4 5 6 10 11 12"
= todos os valores armazenados no mesmo índice - usando eco, você não verá nenhuma diferença. Para uma impressão rápida da matrizdeclare -p array
, você retornará os indeces reais da matriz e o valor correspondente em cada índice.read -d'\n'
método não funcionou para você?read -d'\n'
funciona bem.Para reverter uma matriz arbitrária (que pode conter qualquer número de elementos com quaisquer valores):
Com
zsh
:Com o
bash
4.4+, como asbash
variáveis não podem conter bytes NUL, você pode usar o GNUtac -s ''
nos elementos impressos como registros delimitados por NUL:POSIXly, para reverter a matriz do shell POSIX (
$@
, feita de$1
,$2
...):fonte
Solução de bash pura, funcionaria como uma linha.
fonte
rev+=( "${array[i]}" )
parece mais simples.você também pode considerar usar
seq
no freebsd, você pode omitir -1 parâmetro de incremento:
fonte
Bater
Ou
Resultado
7 6 5 4 3 2 1
Versão
fonte
tac
já foi mencionado: unix.stackexchange.com/a/412874/260978 , unix.stackexchange.com/a/467924/260978 , unix.stackexchange.com/a/413176/260978