¿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.


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.


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'.


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

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.