#!/usr/bin/perl # # droplinebreak: remove newlines before/after lines containing regex. # # 2006-12-13: Written by Steven J. DeRose, sderose\@acm.org. # 2008-08-31 sjd: BSD. # # To do: # Option to *replace* the linebreaks instead of just dropping them, # such as to put in a field-delimiter. use strict; use Getopt::Long; my $version = "2008-08-31"; my $expr = ""; my $dropPreceding = 0; my $dropFollowing = 1; my $help = 0; my $lineends = "U"; my $quiet = 0; my $replace =""; my $verbose = 0; # Process options Getopt::Long::Configure ("ignore_case"); my $result = GetOptions( "b" => sub { $dropPreceding = 1; $dropFollowing = 1; }, "f" => sub { $dropPreceding = 0; $dropFollowing = 1; }, "p" => sub { $dropPreceding = 1; $dropFollowing = 0; }, "linends=s" => sub { $lineends = uc(substr($ARGV[0]."U",0,1)); }, "h|help|?" => \$help, "q|quiet!" => \$quiet, "replace=s" => \$replace, "v|verbose+" => \$verbose, "version" => sub { die "Version of $version, by Steven J. DeRose, sderose\@acm.org.\n"; } ); if ($help) { showUsage(); exit; } ($result) || die "Bad options.\n"; # Validate and default options $lineends = substr($lineends."U",0,1); (index("MDU",$lineends) >= 0) || die "Unknown line-end type $lineends.\n"; my $expr = shift;; ($expr) || die "No regex specified.\n"; ################################################################################ my $last = 0; # No pending line-break from prior line. open my $fh, "<&STDIN"; while (my $l = <$fh>) { chomp($l); if ($l !~ m/$expr/) { # If this line does not match if ($last) { printBreak(); } print $l; $last = 1; } else { # If this line does match if ($last) { # Prior line did *not* drop intervening line break if ($dropPreceding) { if ($replace) { print "$replace"; } } else { printBreak(); } } print $l; if ($dropFollowing) { $last = 0; # Definitely drop this trailing one if ($replace) { print "$replace"; } } else { $last = 1; # keep following newline, unless next line pre drops it. } } } # while not EOF if ($last) { printBreak(); } close $fh; exit; ################################################################################ sub printBreak { if ($lineends eq "M") { print "\r"; } elsif ($lineends eq "D") { print "\r\n"; } else { print "\n"; } } ################################################################################ sub showUsage() { print " Usage: droplinebreak [options] 'regex' Delete the linebreak at the end of lines that match the (Perl-style) regex. (the line need not match in its entirety -- use ^ and \$ if you want that). Options: -b Drop line-ends preceding *and* following each matched line. -f Drop line-end following each matched line (the default). -linends t Output M (mac), D (dos), or U (*nix default) line-ends. -p Drop line-end preceding each matched line. -q Suppress most messages. -r 'string' Put in this string in place of the dropped line breaks. -version Display version info and exit ($version, sjd). Known bugs and limitations: The -r option is not fully tested. "; }