7

How do I construct a list like this:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

Where I run command 15 or something. Or if I specify 100 it would make it with 100 numbers or 10000 and it would make it like this but 10000 numbers.

It should be five numbers on each line (as seen above).

15

you simply do

seq 1 n | xargs -n 5 echo

n being the number you want to reach

If your OS has bash but not seq, here is an alternative (thx to @cuonglm and @jimmyj for their remarks)

echo {1..n} | xargs -n5

(you may have to be careful when reaching very high number with that one, depending on the OS and bash version, and if bash actually tried to expand first or in that case is clever enough to feed little by little without trying to fit the whole 1..n as a string in memory and feed that to echo...)

And thanks to cuonglm and StephaneChazelas, I add an alternative that is very, very less CPU heavy than my first xargs solution (in which xargs calls /bin/echo, instead of being able to use the shell's builtin, every 5 numbers) (it's probably similar to the 2nd one where xargs doesn't invoke echo) :

printf '%s %s %s %s %s\n' {1..n}

That 2nd and 3rd solution differs from the 1st in that the shell have first to expand 1..n, before printf (or xargs) can start printing, if I'm not mistaken... so it starts later (especially if n is big)... And could reach some limits (line length, or memory, depending on the implementation and the OS) if n is very big.

  • 2
    +1 Far better readable than my solution. The first 1 in seq 1 15 is not really necessary. – Anthon Nov 5 '14 at 16:19
  • 1
    echo isn't necessary either. – Hauke Laging Nov 5 '14 at 16:20
  • 1
    Even better: echo {1..100} | xargs -n5 – jimmij Nov 5 '14 at 16:20
  • I agree with both remarks, but I much prefer to let them there : it's far more readable and portable to show how it really works (than just how it could be "golfscripted" to fit this particular example starting at 1 and only displaying numbers) ^^ (teach a person to fish /vs/ give this specific fish) – Olivier Dulac Nov 5 '14 at 16:22
  • 1
    @OlivierDulac: seq is on GNU system only. You can have bash on other *nix. – cuonglm Nov 5 '14 at 16:28
8

Pure coreutils:

$ seq 15 | paste - - - - - 
1   2   3   4   5
6   7   8   9   10
11  12  13  14  15

Pure perl:

$ perl -e '@a=1..15; while($i<=$#a){print "@a[$i..$i+4]\n";$i+=5}'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

GNU grep (shamelessly stolen from @1_CR):

$ echo {1..15} | grep -oP '(\d+ ){4}\d+'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

If you don't mind leading 0s:

$ echo {01..15} | fold -sw 16
01 02 03 04 05 
06 07 08 09 10 
11 12 13 14 15

And if you do:

$ echo {01..15} | fold -sw 16 | sed 's/0\([1-9]\) /\1 /g'
1 2 3 4 5 
6 7 8 9 10 
11 12 13 14 15

Any of these can be made into a function that takes a number as input and prints the corresponding list. For example,

printnums(){
 seq $1 | paste - - - - - 
}

You can then run

$ printnums 30
1   2   3   4   5
6   7   8   9   10
11  12  13  14  15
16  17  18  19  20
21  22  23  24  25
26  27  28  29  30
  • @DisplayName you can copy/paste the lines from my example directly into your terminal, that will make the function available to that terminal. Alternatively, add the lines to your shell's initialization file (~/.bashrc if you're running bash) and they will be available to all terminals. The $1 is simply the first argument given to the function. For more details see here. – terdon Nov 5 '14 at 18:33
  • 1
    Yet another example with column: echo -e "\n"{1..100} | column -c40 -x – jimmij Nov 5 '14 at 18:34
  • @jimmij damn! I knew I was missing one! Why not post that as an answer? – terdon Nov 5 '14 at 18:35
  • Why put all of these in one answer? – Sparr Nov 5 '14 at 21:16
  • @Sparr why would I split them up? It just clutters the site with more answers than needed and stinks of rep whoring. – terdon Nov 5 '14 at 21:24
5

With printf and brace expansion:

printf '%s %s %s %s %s\n' {1..15}
4

With zsh:

$ print -aC5 {1..15}
1   2   3   4   5
6   7   8   9   10
11  12  13  14  15

$ autoload zargs # if not in ~/.zshrc
$ zargs -n 5 {1..15} -- echo
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

$ printf '%s %s %s %s %s\n' {1..15}
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

(that latter one also works in recent versions of ksh93 or bash).

2

using looping :

for x in {1..15};do echo -n "$x ";if [ $(($x%5)) -eq 0 ];then echo ; fi done

output:

1 2 3 4 5 
6 7 8 9 10 
11 12 13 14 15 
  • if ! ((x%5)); then echo or if ((x%5 == 0)); then echo – Paused until further notice. Nov 6 '14 at 17:27
  • 1
    whats new?? here?? – Hackaholic Nov 6 '14 at 17:33
  • [ $(($x%5)) -eq 0 ] is unnecessarily verbose. – Paused until further notice. Nov 6 '14 at 17:35
  • 1
    its not unnecessary, you can do like this or can be done in your way its just different way – Hackaholic Nov 6 '14 at 17:40
2

With awk you can say:

seq 15 | awk 'ORS=NR%5?FS:RS'

It returns:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

Basically, it changes the output record separator (line separator) by either a field separator (space, as default) or a record separator (new line, as default). So if the number of line is multiple of 5, a new line is added; otherwise, a space.

I wrote a broader explanation in a similar question: bash/sed/awk/etc remove every other newline.

1

You can use seq, tr and sed:

seq 15 | tr '\n' ' ' | sed 's/\([0-9]* [0-9]* [0-9]* [0-9]* [0-9]* \)/\1\
/g'

Or as an optimised combination of the answers by Olivier, Benoit and me (in his comments):

seq 15 | xargs -n 5
  • You don't need tr, use seq -s" " 15 instead. – cuonglm Nov 5 '14 at 16:26
1

All the elegant solutions were taken...so with GNU awk and bash

echo {1..15} | awk -v RS='[[:space:]]' '{ORS=NR % numcols?RT:"\n"; print}' numcols=5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

or with GNU grep

echo {1..15} | grep -oE '([[:digit:]]+[[:blank:]]+){4}[[:digit:]]+'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.