34

I know the command seq to generate sequence of integers, one per line, but I would like to ask two questions:

  1. Is it possible to write the numbers of the sequence in the same line?

  2. Is it possible to create a string made of the sequence of numbers separated by a white space?

cuonglm
  • 153,898
Salsiccio
  • 441
  • The shell treats newlines like spaces as argument separators. So, while seq has a separator argument, and even simpler thing to say is just echo $(seq 1 10) – user3188445 Jul 26 '15 at 20:07
  • 1
    @user3188445, it's the split+glob operator doing that (that use the IFS special variable that by default does contain space and newline but can be changed), it's separate from the word tokenization done by the shell. – Stéphane Chazelas Jul 30 '15 at 11:47

5 Answers5

45

With bash, zsh and ksh93, you can use {start..end..step} brace expansion form:

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
cuonglm
  • 153,898
31

GNU seq takes separator (-s) option :

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

$ var="$(seq -s ' ' 1 5)"
$ echo "$var"
1 2 3 4 5
heemayl
  • 56,300
17

Portable to all shells and any system that has seq (as this questions is tagged)

If start is 1:

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

Otherwise:

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

With bc:

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

In bash

echo {1..10}

Note:

This echo solution works if the value of IFS contains a newline, which it does by default.
By default IFS is set to the sequence <space><tab><newline>. And is reset for each clean start of the shell. But, if you have any concern that it may have changed in some extreme corner case, we have several solutions.

Under bash, zsh, ksh just use: IFS=$' \t\n' (skip all the rest of this answer).


However, resetting the value of IFS under sh may be complex Read the complete detail here.

Unset IFS.

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

will always work. Provided that there will be no code below (or child scripts) that need IFS set, such as a script which does OldIFS="$IFS".

Correct solution.

Using a trick for sh:

sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd'  # correct.
  • Comments are not for extended discussion; this conversation has been moved to chat. – terdon Jul 30 '15 at 10:47
  • 1
    Most sh implementations will ignore the IFS found in the environment (exceptions are some ash derivatives, very old versions of some Bourne shells and recent versions of posh). Note that you can simply do IFS='<space><tab><newline>' where those <space>, <tab>, <newline> are the corresponding literal characters. – Stéphane Chazelas Jul 30 '15 at 11:51
4

Use this:

string="$(seq -s " " 1 10)"
Cyrus
  • 12,309
0
seq 10 |xargs

...or...

seq 10 |paste -s -

Both of the commands above will separate the integers by whitespace. xargs defaults to imitating /bin/echo and so each integer is separated by a single space. It will default to a max command line length of 128K, though. You can adjust this...

seq 100000 | xargs -s2093009 | wc -l

...prints 1. I the value for-s here isn't arbitrary - I got it after trying a higher value (which apparently worked anyway) but afterward xargs printed the helpful message:

-s value should be <2093010

paste is one of two (to my knowledge) POSIX-sanctioned utilities for handling lines of arbitrary length:

paste specification application usage:

Most of the standard utilities work on text files. The cut utility can be used to turn files with arbitrary line lengths into a set of text files containing the same data. The paste utility can be used to create (or recreate) files with arbitrary line lengths.

text files

A file that contains characters organized into zero or more lines. The lines do not contain NUL characters and none can exceed {LINE_MAX} bytes in length, including the \newline character. Although POSIX.1-2008 does not distinguish between text files and binary files (see the ISO C standard), many utilities only produce predictable or meaningful output when operating on text files. The standard utilities that have such restrictions always specify text files in their STDIN or INPUT FILES sections.

paste defaults to a tab delimiter, and so there will be a tab between each integer following the second command. You can...

seq 10 |paste -sd ' ' - 

...use the -delimiter switch to alter that behavior,

mikeserv
  • 58,310
  • seq 10 | xargs works fine, but because of command line limits,seq 100000 | xargs outputs 5 \n delimited lines (on my system) – Peter.O Jul 26 '15 at 20:36
  • @Peter.O - paste andcutare the two POSIX sanctioned utilities for working with lines of arbitrart length. That said,xargs | xargsis an option. Or elseseq 100000|tr \n \ ` – mikeserv Jul 26 '15 at 20:56
  • Comments are not for extended discussion; this conversation has been moved to chat. – terdon Jul 28 '15 at 07:11
  • @BinaryZebra - no it doesn't - not like you think it does. Why not try setting $IFS to a number? And in bash its godawful slow anyway. In your answer you talk about sh - you don't even need to set $IFS in that context - it will be passed in via the environment if it is set there. And it's no shorter than seq 100000|paste -s which beats it performance-wise 5:1. And paste doesn't come w/ any gotchas. – mikeserv Jul 28 '15 at 07:36
  • @BinaryZebra - come on, why would I lie? Do I have a sizable answer profile on this site because I enjoy disseminating misinformation? Or maybe it's because I like helping people and enjoy the challenge of learning while I do? Which do you think is more plausible? I like $IFS - I use it all of the time - but I don't use it unless I set it and neither should you. Especially you shouldn't recommend to random strangers who don't know any better thay should do so. Don't leave it to chance - it's a computer program. It's a bug if it behaves unexpectedly - why allow that it might? – mikeserv Jul 28 '15 at 08:20