[EDIT: Fixed whitespace trimming]
[EDIT #2: Strip trailing blank lines from end of file]
perl -i.bak -pe 'if (defined $x && /\S/) { print $x; $x = ""; } $x .= "\n" x chomp; s/\s*?$//; 1 while s/^(\t*) /$1\t/; if (eof) { print "\n"; $x = ""; }' **/*(.)
This strips trailing blank lines from the file, but leaves exactly one \n
at the end of the file. Most tools expect this, and it will not show up as a blank line in most editors. However if you do want to strip that very last \n
, just delete the print "\n";
part from the command.
The command works by "saving up" \n
characters until a line containing a non-blank character is seen -- then it prints them all before processing that line.
Remove .bak
to avoid creating backups of the original files (use at your own risk!)
\s*?
matches zero or more whitespace characters non-greedily, including \r
, which is the first character of the \r\n
DOS line-break syntax. In Perl, $
matches either at the end of the line, or immediately before a final \n
, so combined with the fact that *?
matches non-greedily (trying a 0-width match first, then a 1-width match and so on) it does the right thing.
1 while s/^(\t*) /$1\t/
is just a loop that repeatedly replaces any lines beginning with any number of tabs followed by 4 spaces with one more tab than there was, until this is no longer possible. So it will work even if some lines have been partially converted to tabs already, provided all \t
characters start at a column divisible by 4.
I haven't seen the **/*(.)
syntax before, presumably that's a zsh
extension? If it worked with sed
, it will work with perl
.