Joe
Joe

Reputation: 3620

Require exactly 1 trailing newline in a file

I have a mix of files with various ways of using trailing new lines. There are no carriage returns, it's only \n. Some files have multiple newlines and some files have no trailing newline. I want to edit the files in place.

How can I edit the files to have exactly 1 trailing newline?

Upvotes: 2

Views: 134

Answers (4)

zdim
zdim

Reputation: 66881

Replace all trailing new lines with one?

$text =~ s/\n+$/\n/;

This leaves the file with one newline at the end – if it had at least one to start with. If you want it to be there even if the file didn't have one, replace \n+ with \n*.

For the in-place specification, implying a one-liner:

perl -i -0777 -wpe 's/\n+$/\n/' file.txt

The meaning of the switches is explained in Command Switches in perlrun.


Here is a summary of the switches. Please see the above docs for precise explanations.

  • -i changes the file "in place." Note that data is still copied and temporary files used

  • -0777 reads the file whole. The -0[oct|hex] sets $/ to the number, so to nul with -0

  • -w uses warnigs. Not exactly the same as use warnings but better than nothing

  • -p the code in '' runs on each line of file in turn, like -n, and then $_ is printed

  • -e what follows between '' is executed as Perl code
    -E is the same but also enables features, likesay

Note that we can see the equivalent code by using core O and B::Deparse modules as

perl -MO=Deparse -wp -e 1

This prints

BEGIN { $^W = 1; }
LINE: while (defined($_ = <ARGV>)) {
    '???';
}
continue {
    print $_;
}
-e syntax OK

showing a script equivalent to the one liner with -w and -p.

Upvotes: 3

Ed Morton
Ed Morton

Reputation: 203664

The solutions posted so far read your whole input file into memory which will be an issue if your file is huge. This only reads contiguous empty lines into memory:

awk -i inplace '/./{printf "%s", buf; buf=""; print; next} {buf = buf $0 ORS}' file

The above uses GNU awk for inplace editing.

Upvotes: 1

William Pursell
William Pursell

Reputation: 212268

perl -i -0 -pe 's/\n\n*$/\n/' input-file

Upvotes: 1

John1024
John1024

Reputation: 113864

To change text files in-place to have one and only one trailing newline:

 sed -zi 's/\n*$/\n/'

This requires GNU sed.

-z tells sed to read in the file using the NUL character as a separator. Since text files have no NUL characters, this has the effect of reading the whole file in at once.

-i tells GNU sed to change the file in place.

s/\n*$/\n/ tells sed to replace however many newlines there are at the end of the file with a single newline.

Upvotes: 4

Related Questions