¿Cómo producir un rango con el paso n en bash? (generar una secuencia de números con incrementos)

143

La forma de iterar sobre un rango en bash es

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

¿Cuál sería la sintaxis para iterar sobre la secuencia con un paso? Digamos, me gustaría obtener solo un número par en el ejemplo anterior.

SilentGhost
fuente
Números pares, multiplique i por 2.: P
Joey Robert
la multiplicación es bastante fea, debería decir
SilentGhost
2
@Omnifarious, no estaría tan seguro. OS X todavía viene con 3.2, por ejemplo. Yo diría que se debe aceptar el bucle de estilo C.
Eli Korvigo

Respuestas:

195

Lo haría

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

(aunque, por supuesto seq 0 2 10, producirá la misma salida por sí solo).

Tenga en cuenta que seqpermite números de punto flotante (por ejemplo, seq .5 .25 3.5) pero la expansión de llaves de bash solo permite enteros.

caos
fuente
44
Me arriesgaré a adivinar que el voto negativo se debió a que su respuesta fue genérica a 'sh', y no específica a 'bash'. El enfoque puro de Bash {begin end step} funciona un poco mejor. El método 'seq' más antiguo es útil en sistemas de memoria más antiguos o más pequeños como busybox. Voté tanto tu respuesta como la de TheBonsai. :)
Scott Prive
66
Prefiero $ (...) a backquotes. Las comillas inversas no anidan sanamente.
Omnifarioso
seq 1000000 1000010 solo hace flotantes, de hecho, ¡no hay forma de hacerlo entero! Trabajos de expansión de llaves.
hmijail llora a los reenviados
112

La expansión de llaves de Bash 4 tiene una función de paso:

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

No importa si Bash 2/3 (estilo C para bucle, vea las respuestas anteriores) o Bash 4, preferiría cualquier cosa sobre el comando 'seq'.

TheBonsai
fuente
1
y por cierto, ¿sabes si bash4 es el predeterminado en cualquier sistema operativo principal?
SilentGhost
3
Bash4 todavía no es convencional, no. ¿Por qué no seq? Bueno, digámoslo con las palabras del bot en el canal IRC #bash: "seq (1) es un comando externo altamente no estándar que se utiliza para contar hasta 10 en tontos procedimientos de Linux".
TheBonsai
Entiendo que seq es parte de coreutils. ¿Qué no es estándar al respecto? argumentos? gracias por tu ayuda.
SilentGhost
44
Estos argumentos pueden o no contar para usted: * hay suficientes sistemas sin GNU coreutils (pero Bash instalado) * crea un proceso externo innecesario * confía en la idea de que todos los 'seq' hacen lo que su 'seq' hace * es no estandarizado por la ISO
TheBonsai
3
@becko Si el paso está almacenado en la variable i, entonces no puede hacerlo for {0..10..${i}}... falla.
Nehal J Wani
72

Pure Bash, sin un proceso adicional:

for (( COUNTER=0; COUNTER<=10; COUNTER+=2 )); do
    echo $COUNTER
done
Fritz G. Mehner
fuente
10
+1 Porque el paso también puede ser reemplazado por una variable.
Nehal J Wani
1
Creo que esto es realmente lo que la mayoría de la gente probablemente quiere: una forma simple de hacer un ciclo con un valor de paso prescrito. Suena más simple que todas las respuestas basadas en seq, y es una sintaxis más clara que la expansión de llaves Bash4, y parece que permitiría variables (no lo he intentado, pero la sintaxis definitivamente lo sugiere).
tobylaroni
Funciona en Bash 3, a diferencia de la respuesta de @ TheBonsai.
srcerer
Incluso resuelve la variable, ((i = "$ first"; i <= "$ last"; i + = "$ step")). No es tan fácil con llaves y seq.
Blaa_Thor
20
#!/bin/bash
for i in $(seq 1 2 10)
do
   echo "skip by 2 value $i"
done
z -
fuente
seq es un comando de Linux. Esto no estará disponible en Mac OS X o FreeBSD.
Dereckson
55
FWIW seq está disponible en mi OS X Mavericks estándar 10.9.1
Mark Setchell
He probado otros sintaxis, pero ese es el único que funciona para mi en un pequeño CentOS. @z - me ha salvado el día: 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
fuente