Como exibir números na ordem inversa usando seq (1)?


36

Eu tenho iterado sobre números em várias ordens. Eu posso exibi-los em ordem crescente, mesmo com etapas como:

$ seq --separator="," 1 10
1,2,3,4,5,6,7,8,9,10
$ seq --separator="," 1 2 10
1,3,5,7,9

Também posso exibi-los em ordem inversa, nem contínua nem passo a passo.

$ seq --separator="," 10 1   
$ seq --separator="," 10 2 1

Nenhuma saída para os comandos acima.

Meus detalhes do shell:

$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

Deixe-me saber como eu seria capaz de exibir os números em ordem decrescente?


10
Para futuros leitores, seqé uma ferramenta completamente fora do padrão e não há garantia de que quaisquer duas implementações sejam iguais. Se você precisar escrever um loop que itere para trás sobre números no bash, use for ((i=$max;i>=0;i--)) …ou algo semelhante.
kojiro

Respostas:


50

use incremento negativo

seq -s, 10 -2 1
10,8,6,4,2

20

Em geral, você não deseja usar seq, não é portátil (mesmo entre ambientes Linux padrão). Se você estiver usando ksh, zsh ou bash4 +, poderá usar a expansão de chave:

echo {10..1..2} | tr " " ,
10,8,6,4,2

11
É curto e rápido, mas estou na versão mais antiga do bash.
mtk

20
Resposta doce, mas há alguma ironia quando você ressalta que seqnão é padrão e, em seguida, usa a expansão de chave somente bash-4. ;)
kojiro

@kojiro - Nenhum argumento para ser honesto ;-) Minha principal preocupação não é se o comando existe (isso pode ou não ser importante, dependendo da distribuição do script / etc), mas se o comando é executado conforme o esperado por o autor. A expansão de chaves do bash4 quase tem isso garantido (se funcionar, funciona como o esperado), enquanto seqnão funciona.
Chris Baixo

11
Por que não é portátil? Você tem fontes ou provas? Estou interessado.
Benoit Duffez

15

Outra maneira no bash puro, ksh ou zsh:

for ((i=10;i>0;i-=2)) ; do echo -n "$i," ; done

Uma maneira pura de POSIX sh:

i=10
while [ "$i" -gt 2 ]; do printf "$i,"; i=$((i-2)); done
echo "$i"

11
forA segunda expressão de deve ser o teste e a terceira a etapa.
manatwork

7

Agora, os POSIX padrão:

awk 'BEGIN{for (i = 10; i > 0; i -= 2) print i}' | paste -sd , -

(curiosamente, com mawk(e em menor grau gawktambém) muito mais rápido que o GNU seqem i = 10000000vez de i = 10)

Ou

i=10; set --
while [ "$i" -gt 0 ]; do
  set -- "$@" "$i"
  i=$(($i - 2))
done
IFS=,
echo "$*"

(seria mais eficiente apenas com um pequeno número de iterações, especialmente com bash)

Ou

echo 'for(i=10;i>0;i-=2) i' | bc | paste -sd , -

(que suportaria números de qualquer tamanho, mas observe que após um certo número de dígitos (números maiores que 10 70 no código do idioma POSIX), as linhas seriam quebradas com barras invertidas)


11
No GNU bc, você pode evitar a quebra de linha configurando BC_LINE_LENGTH=0no ambiente. Não há tanta sorte em outras implementações.
Gilles 'SO- stop be evil'

11
Por que usar os argumentos posicionais em vez de alternar s=$s,$iou chamar echo -n/ echo \c/ printf?
Gilles 'SO- stop be evil'

2

Você pode reverter a ordem usando tac(cat in reverse). Mesmo que seqdeva se comportar de maneira diferente em vários sistemas, acho que o seguinte deve ser o mais portátil possível:

$ seq 1 10 | tr '\012' ',' | sed 's/,$//'; echo
1,2,3,4,5,6,7,8,9,10
$ seq 1 10 | tac | tr '\012' ',' | sed 's/,$//'; echo
10,9,8,7,6,5,4,3,2,1
$

2

Tente com:

   seq [OPTION]... FIRST INCREMENT LAST

Exemplo:

$ seq 10 -1 1

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.