In Perl: To match consecutive newlines using a regex, you cannot read in line-by-line mode. Which is why we slurp the file into a single string.
my $str = do { local $/; <DATA> }; # slurp the file into a single string
$str =~ s/\n\n?\K\n+//g;
print $str;
The substitution regex matches a single newline \n
, followed by an optional newline \n?
, which it keeps \K
, followed by 1 or more newlines \n+
, which it removes. Since all quantifiers are greedy, this will allow the ?
to preserve the case of two newlines when there are 3 or more.
Case \n\n?\K\n+ explanation result
\n 1 x x no match, no substitution no change
\n\n 1 0 1 match, skip, match 1 time \n remove \n
\n\n\n+ 1 1 1+ match, match, match 1+ times \n\n remove \n+
Or if you like it as a one-liner:
perl -0777 -pe's/\n\n?\K\n+//g' file
Add -i
option to in-place edit a file when you are satisfied the changes work as expected. -i.bak
to save backup.