34

How can I use text-processing tools to insert a new line after every N lines?

Example for N=2:

INPUT:

sadf
asdf
yxcv
cxv
eqrt
asdf

OUTPUT:

sadf
asdf

yxcv
cxv

eqrt
asdf
LanceBaynes
  • 40,135
  • 97
  • 255
  • 351

6 Answers6

48

With awk:

awk ' {print;} NR % 2 == 0 { print ""; }' inputfile

With sed (GNU extension):

sed '0~2 a\\' inputfile

With bash:

#!/bin/bash
lines=0
while IFS= read -r line
do
    printf '%s\n' "${line}"
    ((lines++ % 2)) && echo
done < "$1"
  • 2
    Arithmetic evaluation can be used directly as condition, no need for the [[ ]] to test: while read line; do echo "$line"; ((lines++ % 2)) && echo; done. – manatwork Oct 29 '11 at 14:57
  • 2
    Be aware that the above documented command sed '0~2 a\ ' adds a space to each inserted newline. If you wanted to add a newline after each line, any of these similarly work: sed '0~1 a\ ', sed 'a\ ', or just sed G. – Asclepius Nov 07 '13 at 19:20
7

sed (GNU)

With (GNU) sed:

sed '0~2G'

Short (ugly for N=100):

sed 'n;G'

man sed explains ~ as:

first ~ step
Match every step'th line starting with line first. For example, ``sed -n 1~2p'' will print all the odd-numbered lines in the input stream, and the address 2~5 will match every fifth line, starting with the second. first can be zero; in this case, sed operates as if it were equal to step. (This is an extension.)

sed (other)

With other sed (Count new lines):

sed -e 'p;s/.*//;H;x;/\n\{2\}/{g;p};x;d'

Or, to be more portable, written as (remove comments for some versions of sed) :

sed -e '             # Start a sed script.
         p            # Whatever happens later, print the line.
         s/.*//       # Clean the pattern space.
         H            # Add **one** newline to hold space.
         x            # Get the hold space to examine it, now is empty.
         /\n\{2\}/{   # Test if there are 2 new lines counted.
             g        # Erase the newline count.
             p        # Print an additional new line.
           }          # End the test.
         x            # match the `x` done above.
         d            # don't print anything else. Re-start.
       '              # End sed script.

awk

With awk, probably:

awk '1 ; NR%2==0 {printf"\n"} '
6

Using paste

 paste -d'\n' - - /dev/null <file
iruvar
  • 16,725
5
sed n\;G <infile

... is all you need ...

For example:

seq 6 | sed n\;G

OUTPUT:

1
2

3
4

5
6

...(and a blank follows the 6 as well)...or...

seq 5 | sed n\;G

OUTPUT:

1
2

3
4

5

(and no blank follows the 5)

If a blank should always be omitted in a last line case:

sed 'n;$!G' <infile
mikeserv
  • 58,310
3

Another awk flavour:

awk '{ l=$0; getline; printf("%s\n%s\n\n", l, $0) }'
glenn jackman
  • 85,964
0

Using Perl

~$ perl -ne 'print $_; if ($. % 2 == 0) { print "\n"};'  file

Using Raku (formerly known as Perl_6)

~$ raku -ne '.put; if (++$ %% 2) { print "\n"};'  file

The Perl answer uses $_ which is Perl's topic variable, and $. which is Perl's line-number variable. If the line number % modulo 2 equals zero, insert a \n newline.

The Raku answer uses $_ but in an abbreviated form: .put is short for $_.put. The Raku answer uses ++$ an anonymous pre-incrementing counter variable. Raku's %% 'Divisibility operator' is set to return True if ++$ % 2 == 0, so again (like the Perl answer), a \n newline is inserted.

Sample Input:

sadf
asdf
yxcv
cxv
eqrt
asdf

Sample Output:

sadf
asdf

yxcv cxv

eqrt asdf


Perl References:
https://perldoc.perl.org
https://www.perl.org

Raku References:
https://docs.raku.org
https://raku.org

jubilatious1
  • 3,195
  • 8
  • 17