25

Would like to have each line in a file repeated a fixed number of times.

e.g. have each line repeated four times:

a
b
c

becomes:

a
a
a
a
b
b
b
b
c
c
c
c

I've done some searching, and there are a lot of questions and answers along the lines of doing the reverse, e.g. merging duplicate lines into single lines, and maybe a few about doubling lines by printing them again.

It would be easy to do this in C, but I wish I knew more about the native commands so I wouldn't have to resort to these kinds of one-off throw-aways all the time.

7 Answers 7

41

I wonder if this is turning into a golf match:

sed 'p;p;p' 
awk '1;1;1;1' 
perl -lpE 'say;say;say'   # if Paul McCartney and Michael Jackson were hackers...

Explanation:

sed's p command is to print the current line. The default behaviour is to print the current line just before moving to the next line (that's why sed has -n to allow you to turn it off). Some older seds don't have the semicolon (I think) so it's possible you might have to do sed -e p -e p -e p

Awk works with condition {action} pairs. If the action is omitted, the default is to print the current line if the condition returns true. Awk, like many C-like languages, treats 1 as true. (For completeness, if the condition is omitted, the action will be executed for each record.)

Many perl functions take advantage of the "default" variable. This one-liner is equivalent to (on perl 5.16):

$ perl -MO=Deparse -lpE 'say;say;say'
BEGIN { $/ = "\n"; $\ = "\n"; }
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    say $_;
    say $_;
    say $_;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
3
  • 2
    +1, if it is, you're winning :) What exactly does the 1 do in awk? Shorthand for print $0?
    – terdon
    Commented Jul 5, 2013 at 16:15
  • 4
    Awk statements are made up of a condition and a block, either are optional, but one must be present. The default condition is 1 (true); the default block is equivalent to {print}. So the statement 1 would mean to print the current line buffer ({print}). ({print} and {print $0} are mostly the same, qed.)
    – Arcege
    Commented Jul 5, 2013 at 17:49
  • 1
    I've never heard of a sed that doesn't support semicolons as command terminators; is there really such a thing?
    – Wildcard
    Commented May 6, 2016 at 16:41
27
  • Perl:

    perl -ne 'for$i(0..3){print}' file
    

    and I have to add this one posted as a comment by @derobert because it is just cool:

    perl -ne 'print "$_" x4'
    
  • awk and variants:

    awk '{for(i=0;i<4;i++)print}' file
    
  • bash

    while read line; do for i in {1..4}; do echo "$line"; done; done < file
    
3
  • 1
    awk's for not needs braces if there is only one command to repeat. And perl is simpler if you use foreach loop: for$i(0..3){print}.
    – manatwork
    Commented Jul 5, 2013 at 16:38
  • 4
    Alternative perl: perl -ne 'print(($_)x4)'. Also, you should quote $line (in echo) in your bash version.
    – derobert
    Commented Jul 5, 2013 at 16:46
  • In my case I needed Windows line-endings. as seen here can achieve with BEGIN { ORS="\r\n" } Commented Oct 27, 2015 at 17:16
5
sed -n '{p;p;p;p;}' file

awk '{print;print;print;print;}' file
0
5

You can do this without requiring sed, perl, or awk.

$ for i in `cat <file>` ; do seq <#> <#> | xargs -i -- echo $i ; done

or using a while loop:

$ while read i ; do seq <#> <#> | xargs -i -- echo $i ; done < <file>

Examples

for loop
$ for i in `cat sample.txt` ; do seq 1 3 | xargs -i -- echo $i ; done
a
a
a
b
b
b
c
c
c
while loop
$ while read i; do seq 1 2| xargs -i -- echo $i;done < sample.txt
a
a
b
b
c
c
2
  • 1
    I think the for loop version will break on any lines containing whitespace, so the while loop should be preferred. Otherwise, +1 since I'm a sucker for shell solutions.
    – evilsoup
    Commented Jul 6, 2013 at 13:27
  • 1
    @evilsoup - yes someone else mentioned this as well on some code I posted on another Q&A. I think that's the primary advantage of while over for, the while loop is tolerant of the $IFS separator and will split on end-of-line whereas the for splits on $IFS.
    – slm
    Commented Jul 6, 2013 at 13:30
2

Using purely shell:

repeats=4
while read line; do yes $line|head --lines=$repeats; done < infile > outfile
3
  • Does somebody know how to make yes consider --help as a string instead of an option? [consider the case where line is --help or another option]
    – user176581
    Commented Jul 6, 2013 at 15:41
  • 1
    yes, yes -- --help Commented Sep 13, 2015 at 0:01
  • 1
    Using yes and head means this is not "purely shell" Commented Aug 15, 2019 at 16:37
2

This might work for you (GNU sed):

sed 'h;:a;s/[^\n]\+/&/4;t;G;ba' file

Will repeat each line 4 times.

Or if you prefer:

sed 'h;:a;s/\n/&/3;t;G;ba' file

Where you repeat each line 3 more times.

2

@potong 's answer does not work with empty lines, replacing \+ with * should fix it:

sed 'h;:a;s/[^\n]*/&/4;t;G;ba' file
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .