Bash: secuencia de números en la misma línea

20

Conozco el comando seqpara generar una secuencia de enteros, uno por línea, pero me gustaría hacer dos preguntas:

  1. ¿Es posible escribir los números de la secuencia en la misma línea?

  2. ¿Es posible crear una cadena hecha de la secuencia de números separados por un espacio en blanco?

Salsiccio
fuente
El shell trata las nuevas líneas como espacios como separadores de argumentos. Entonces, mientras que seq tiene un argumento separador, y algo más simple que decir es soloecho $(seq 1 10)
user3188445
1
@ user3188445, es el operador split + glob que hace eso (que usa la variable especial IFS que por defecto contiene espacio y nueva línea pero se puede cambiar), es independiente de la tokenización de palabras realizada por el shell.
Stéphane Chazelas

Respuestas:

21

GNU seqtoma la -sopción separator ( ):

$ seq -s ' ' 1 5
1 2 3 4 5

$ var="$(seq -s ' ' 1 5)"
$ echo "$var"
1 2 3 4 5
heemayl
fuente
1
echo $(seq 5)funciona bien.
13

Portátil para todos los shells y cualquier sistema que tenga seq (ya que esta pregunta está etiquetada)

Si inicio es 1:

$ echo $(seq 10)
1 2 3 4 5 6 7 8 9 10

De otra manera:

$ echo $(seq 5 10)
5 6 7 8 9 10

Con bc:

$ echo $(echo "for (i=0;i<=1000;i++) i"| bc)

En bash

echo {1..10}

Nota:

Esta solución de eco funciona si el valor de IFS contiene una nueva línea, lo que hace por defecto.
Por defecto, IFS está configurado en la secuencia <espacio><tabla> <nueva línea> . Y se restablece para cada inicio limpio del shell. Pero, si le preocupa que haya cambiado en algún caso extremo, tenemos varias soluciones.

En bash, zsh, ksh solo use: IFS = $ '\ t \ n' (omita el resto de esta respuesta).


Sin embargo, restablecer el valor de IFS bajo sh puede ser complejo. Lea el detalle completo aquí .

Desarmar IFS.

$ unset IFS; echo $(seq 5 10)                           #Always work.

siempre funcionará Siempre que no haya ningún código a continuación (o scripts secundarios) que necesiten un conjunto IFS, como un script que lo haga OldIFS="$IFS".

Solución correcta

Usando un truco para sh:

sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd'  # correct.

fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
terdon
1
La mayoría de las implementaciones de sh ignorarán el IFS encontrado en el entorno (las excepciones son algunos derivados de cenizas, versiones muy antiguas de algunos shells Bourne y versiones recientes de elegante). Tenga en cuenta que sólo se puede hacer IFS='<space><tab><newline>' cuando los <space>, <tab>, <newline>son los caracteres literales correspondientes.
Stéphane Chazelas
3

Utilizar esta:

string="$(seq -s " " 1 10)"
Ciro
fuente
0
seq 10 |xargs

...o...

seq 10 |paste -s -

Los dos comandos anteriores separarán los enteros por espacios en blanco. xargsel valor predeterminado es imitar /bin/echoy, por lo tanto, cada número entero está separado por un solo espacio. Sin embargo, tendrá una longitud máxima de línea de comando de 128K. Puedes ajustar esto ...

seq 100000 | xargs -s2093009 | wc -l

... imprime 1. I el valor -saquí no es arbitrario: lo obtuve después de probar un valor más alto (que aparentemente funcionó de todos modos) pero luego xargsimprimí el mensaje útil:

-s value should be <2093010

pastees una de las dos utilidades sancionadas por POSIX (que yo sepa) para manejar líneas de longitud arbitraria:

pasteuso de la aplicación de especificación :

La mayoría de las utilidades estándar funcionan en archivos de texto . La cututilidad se puede utilizar para convertir archivos con longitudes de línea arbitrarias en un conjunto de archivos de texto que contienen los mismos datos. La pasteutilidad se puede usar para crear (o recrear) archivos con longitudes de línea arbitrarias.

archivos de texto

Un archivo que contiene caracteres organizados en cero o más líneas. Las líneas no contienen caracteres NUL y ninguno puede exceder los {LINE_MAX}bytes de longitud, incluido el \ncarácter de línea ew. Aunque POSIX.1-2008 no distingue entre archivos de texto y archivos binarios (consulte el estándar ISO C) , muchas utilidades solo producen resultados predecibles o significativos cuando operan en archivos de texto. Las utilidades estándar que tienen tales restricciones siempre especifican archivos de texto en sus secciones STDIN o INPUT FILES .

pasteel valor predeterminado es un delimitador de tabulación, por lo que habrá una tabulación entre cada entero después del segundo comando. Usted puede...

seq 10 |paste -sd ' ' - 

... usa el -dinterruptor eliminador para alterar ese comportamiento,

mikeserv
fuente
seq 10 | xargsfunciona bien, pero debido a los límites de la línea de comando, seq 100000 | xargsgenera 5 \nlíneas delimitadas (en mi sistema)
Peter.O
@ Peter.O - paste and cut` son las dos utilidades sancionadas por POSIX para trabajar con líneas de longitud arbitraria. Dicho eso, xargs | xargses una opción. O bienseq 100000|tr \\n \
mikeserv
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
terdon
@BinaryZebra, no, no lo hace, no como crees que lo hace. ¿Por qué no intentar establecer $IFSun número? Y en bashsu godawful lento de todos modos. En su respuesta, habla de shque, ni siquiera necesita establecer $IFSen ese contexto, se transmitirá a través del entorno si se configura allí. Y no es más corto de lo seq 100000|paste -sque supera su rendimiento 5: 1. Y pasteno viene con ninguna trampa.
mikeserv
@BinaryZebra - vamos, ¿por qué mentiría? ¿Tengo un perfil de respuesta considerable en este sitio porque me gusta difundir información errónea? ¿O tal vez es porque me gusta ayudar a las personas y disfrutar el desafío de aprender mientras lo hago? ¿Cuál crees que es más plausible? Me gusta $IFS, lo uso todo el tiempo, pero no lo uso a menos que lo configure y usted tampoco debería hacerlo. Especialmente no deberías recomendar a extraños al azar que no conocen mejor que deberían hacerlo. No lo deje al azar: es un programa de computadora. Es un error si se comporta inesperadamente, ¿por qué permitir que lo haga?
mikeserv