Como produzir um intervalo com o passo n no bash? (gere uma sequência de números com incrementos)

143

A maneira de iterar em um intervalo no bash é

for i in {0..10}; do echo $i; done

Qual seria a sintaxe para iterar a sequência com uma etapa? Digamos, eu gostaria de obter apenas um número par no exemplo acima.

SilentGhost
fonte
Números pares, multiplicar i por 2.: P
Joey Robert
multiplicação é bastante feio, devo dizer
SilentGhost
2
@ Onnifarious eu não teria tanta certeza. O OS X ainda vem com o 3.2, por exemplo. Eu diria que o loop no estilo C deve ser aceito.
Eli Korvigo 05/10

Respostas:

195

eu faria

for i in `seq 0 2 10`; do echo $i; done

(embora, é claro seq 0 2 10, produza a mesma saída por conta própria).

Observe que seqpermite números de ponto flutuante (por exemplo, seq .5 .25 3.5) , mas a expansão de chaves do bash permite apenas números inteiros.

caos
fonte
4
Arriscarei um palpite de que o voto negativo foi devido à sua resposta ser genérica para 'sh' e não específica para 'bash'. A abordagem pura do Bash {begin end step} tem um desempenho um pouco melhor. O método 'seq' mais antigo é útil em sistemas de memória antiga ou menor, como o busybox. Eu votei tanto na sua resposta quanto na do TheBonsai. :)
Scott Prive
6
Prefira $ (...) a aspas. As aspas posteriores não se aninham de forma saudável.
omniforme
seq 1000000 1000010 apenas flutua, na verdade - não há como fazer números inteiros! Trabalhos de expansão de cinta.
hmijail lamenta os demitidos
112

A expansão do suporte do Bash 4 tem um recurso de etapa:

for {0..10..2}; do
  ..
done

Não importa se o Bash 2/3 (estilo C para loop, veja as respostas acima) ou o Bash 4, eu preferiria qualquer coisa sobre o comando 'seq'.

TheBonsai
fonte
1
e btw, você sabe se o bash4 é o padrão em qualquer sistema operacional principal?
9409 SilentGhost
3
O Bash4 ainda não é popular, não. Por que não seq? Bem, digamos com as palavras do bot no canal de IRC #bash: "seq (1) é um comando externo altamente fora do padrão usado para contar até 10 em howos tolos do Linux".
TheBonsai
meu entendimento é que seq faz parte do coreutils. o que não é padrão nisso? argumentos? Obrigado pela ajuda.
9609 SilentGhost #
4
Estes argumentos podem ou não contar para você: * existem sistemas suficientes sem o GNU coreutils (mas o Bash instalado) * você cria um processo externo desnecessário * você confia na ideia de que todos os 'seq' fazem o que o seu 'seq' faz não padronizada pela ISO
TheBonsai
3
@ecko Se a etapa está armazenada na variável i, você não pode fazer for {0..10..${i}}.. ela falha.
Nehal J Wani
72

Pure Bash, sem um processo extra:

for (( COUNTER=0; COUNTER<=10; COUNTER+=2 )); do
    echo $COUNTER
done
Fritz G. Mehner
fonte
10
+1 Porque a etapa também pode ser substituída por uma variável.
Nehal J Wani
1
Eu acho que isso é realmente o que a maioria das pessoas provavelmente quer - uma maneira simples de fazer um loop com um valor de etapa prescrito. Parece mais simples do que todas as respostas baseadas em seq e é uma sintaxe mais clara que a expansão de chaves Bash4, e parece que permitiria variáveis ​​(eu não tentei isso, mas a sintaxe definitivamente sugere isso).
tobylaroni
Funciona no Bash 3, diferente da resposta de @ TheBonsai.
srcerer
Ele até resolve a variável ((i = "$ first"; i <= "$ last"; i + = "$ step")). Não é tão fácil com chaves e seq.
Blues2_Pedro
20
#!/bin/bash
for i in $(seq 1 2 10)
do
   echo "skip by 2 value $i"
done
z -
fonte
seq é um comando do Linux. Isso não estará disponível no Mac OS X ou no FreeBSD.
Dereckson
5
O FWIW seq está disponível no meu OS X Mavericks 10.9.1 padrão
Mark Setchell
Eu tentei outra sintaxe, mas essa é a única que está funcionando no meu CentOS. @z - salvou o meu dia: D
m3nda
3
> seq 4
1
2
3
4

> seq 2 5
2
3
4
5

> seq 4 2 12
4
6
8
10
12

> seq -w 4 2 12
04
06
08
10
12

> seq -s, 4 2 12
4,6,8,10,12
Mir-Ismaili
fonte