1

I have a file that reads like this:

dog   cat   mouse
apple    orange    pear
red    yellow    green

There is a tab \t separating the words on each row, and a newline \n separating each of the rows. Below the last line, red yellow green there is a blank line due to a newline \n after green. I would like to use Perl to remove the newline.

I have seen a few articles like this How can I delete a newline if it is the last character in a file? that give solutions for Perl, but I would like to do this in hard code so that I can incorporate it into my Perl script. I don't know if this might be possible using chomp, or if chomp works on each line separately (I would like to keep the newline between lines).

Also I have seen previously comments that suggest maintaining a newline at the end of a file because Unix commands work better when a file ends with a newline. However, I have created a script which relies on input files not ending with a newline, therefore I really feel removing the newlines is necessary for my work.

NEW2R
  • 53
  • 6
  • 4
    Why does your script rely on a file not ending with newline? That sounds like a poor script to me. – TLP Mar 31 '21 at 15:35
  • Something like this will work, the chmp removes new lines, the split is on one of more white save. The -lane processes the file a line at a time, inline. perl -lane 'chomp; if ($_) {@list=split(/\s+/); print join("|",@list);}' file1 – Essex Boy Mar 31 '21 at 15:52
  • does `od -c yourfile | tail` end with `g r e e n \n` or `g r e e n \n \n` ? – jhnc Mar 31 '21 at 16:07
  • @TLP I created the script before I knew files were supposed to end with a newline, and much of the script involves count the number of lines. Why is it bad form to not end with a newline? – NEW2R Mar 31 '21 at 16:12
  • @EssexBoy `-l` already does chomp and `-a` does autosplit: `perl -lanE '$_ && say join "|",@F'` – jhnc Mar 31 '21 at 16:17
  • @jhnc The end of the file looks like this: 0017360 \n 0017361 So just a single \n I believe – NEW2R Mar 31 '21 at 16:43
  • If there's a blank line, that would imply that there are 2 `\n` after green. If there is only one `\n`, there is no blank line. – William Pursell Mar 31 '21 at 17:07
  • @WilliamPursell There does appear to be a blank link though. – NEW2R Mar 31 '21 at 17:12
  • If there's a blank line, then there are two newlines after `green`. You almost certainly want to keep one of them. The file with content `one\ntwo\n` has two lines. The file with content `one\ntwo\n\n` has 3 lines, and one of them is blank. The file with content `one\ntwo` is barely even describable as a text file, and is more accurately described as ill formed garbage. – William Pursell Mar 31 '21 at 17:25
  • 1
    Note that the above comment is highly opinionated. A text file does not need to end with a newline, but IMO they ought to. If you have a utility that treats `one\ntwo\n` as a three line file, that utility is broken. – William Pursell Mar 31 '21 at 17:30
  • Fix your program to handle a newline at the end of any line. You are eventually going to run into problems where editors re-add the newline. Instead of duct-taping over the problem, don't make it a problem. Consider the pain people experience in this issue: https://github.com/gohugoio/hugo/issues/1753 – brian d foy Apr 01 '21 at 10:39

1 Answers1

3

You can try this:

perl -pe 'chomp if eof' file.txt

Here is another simple way, if you need it in a script:

open $fh, "file.txt"; 
@lines=<$fh>;          # read all lines and store in array 
close $fh;
chomp $lines[-1];      # remove newline from last line
print @lines;

Or something like this (in script), as suggested by jnhc for the command line:

open $fh, "file.txt"; 
while (<$fh>) { 
  chomp if eof $fh; 
  print; 
}
close $fh;
Donat
  • 4,157
  • 3
  • 11
  • 26
  • Could you give any guidance as to how to do this - or if not, explain what the aspects of your code do? – NEW2R Mar 31 '21 at 17:00
  • `perl -pe 'chomp if eof' file.txt` is a bit shorter – jhnc Mar 31 '21 at 17:02
  • I used `open $fh, "file.txt"; while (<$fh>) { chomp if eof $fh; print; } close $fh;` and that did the trick – NEW2R Mar 31 '21 at 17:22