Samanosuke Akechi
Samanosuke Akechi

Reputation: 361

awk Repeat the values of a column n times

I have a column and I want to repeat it multiple times.

eg for example I want the following column

    1
    2
    3
    4
    5

to repeat n times and become

1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
.
.
.
etc

is this possible?

Upvotes: 0

Views: 2924

Answers (3)

RARE Kpop Manifesto
RARE Kpop Manifesto

Reputation: 2841

Here's a portable awk-based solution to do it using only built in variables with no looping at all :

{m,n,g}awk 'NF += __-(OFS = $-_)^_' RS='^$' FS='^$' ORS= __=3

1 <<<<
2
3
4
1 <<<<
2
3
4
1 <<<<
2
3
4

To repeat each row N times consecutively before the next row, then do

{m,n,g}awk 'NF += __-(OFS = "\n" $-_)^_' FS='^$' __=3

1 <<<<
1 <<<<
1 <<<<
2
2
2
3
3
3
4
4
4

If you wanna duplicate each row horizontally by N times, it's the same concept, slightly different :

{m,n,g}awk 'NF = __ *(OFS = $-_)^_' FS='^$' __=7

10101010101010
11111111111111
12121212121212
13131313131313
14141414141414
15151515151515
16161616161616
17171717171717
18181818181818
19191919191919

You can even make cute numeric pyramids by having the repeat count be based on NR :

{m,n,g}awk 'NF = NR * (OFS=$-_)^_' FS='^$'
10
1111
121212
13131313
1414141414
151515151515
16161616161616
1717171717171717
181818181818181818
19191919191919191919
2020202020202020202020

So if you ever need 2^25 aka 32^5 copies for ASCII string of 2^25 itself, then here's a pretty quick (0.45s) and easy way to get it done with no loops at all :

out9:  256MiB 0:00:00 [ 591MiB/s] [ 591MiB/s] [  <=> ]

( echo 33554432 | mawk2 'NF=(OFS=$-_)^_*$-_' FS='^$'; )  

0.30s user 0.10s system 89% cpu 0.454 total

      1 268435457

Even if you wanna repeat pretty sizable files, it's reasonably speedy fast : e.g. less than 13 secs for 9 x a 1.85 GB file :

 {m,g}awk 'NF += __-(OFS = $-_)^_' RS='^$' FS='^$' ORS= __=9

 out9: 16.6GiB 0:00:12 [1.30GiB/s] [1.30GiB/s] [ <=> ]
  in0: 1.85GiB 0:00:00 [3.42GiB/s] [3.42GiB/s] [========>] 100%            

  5.48s user 4.44s system 77% cpu 12.809 total

  112448475 17851902237 17851902237

If that's too slow for your needs, perhaps this way is a bit faster :

 {m,g}awk '
 BEGIN { FS = RS = "^$" }{__=sprintf("%*s",__, OFS = ORS = _)
         gsub(".", "\\&", __) }   sub(".+",__)'  __=9 


  in0: 1.85GiB 0:00:00 [3.48GiB/s] [3.48GiB/s] [========>] 100%            
 out9: 16.6GiB 0:00:07 [2.12GiB/s] [2.12GiB/s] [ <=> ]

 ( pvE 0.1 in0 < "${m3t}" | LC_ALL=C mawk2 -v __=9 ; )
 0.72s user 4.34s system 64% cpu 7.855 total

 112448475 17851902237 17851902237

Upvotes: 0

Ed Morton
Ed Morton

Reputation: 203684

awk -v n=7 '{s = s $1 ORS} END{for (i=1;i<=n;i++) printf "%s", s}' file

Set n to whatever number you like.

Alternatively, with GNU awk:

awk -v n=7 -v RS='\0' -v ORS= 'END{for (i=1;i<=n;i++) print}' file

Upvotes: 2

Chris Seymour
Chris Seymour

Reputation: 85815

Replace 3 with any value of n and $1 with the column you want to print:

$ for i in {1..3}; do awk '{print $1}' file; done
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5

You could do it just with awk but you would have to store the whole file in memory:

$ awk '{a[NR]=$1}END{for(i=1;i<=3;i++)for(j=1;j<=NR;j++)print a[j]}' file

This is one of those occasions were using the shell constructs actually makes sense.

Upvotes: 2

Related Questions