If you like the /first/, /last/ notation of sed, there is a similar construct in perl, namely the range operator, "..", and, in the context of lines, it works as you wanted the sed construct to work (it can also used as a list generator). The perl script is a bit more verbose than the awk scripts, but it may be more readable:
#!/usr/bin/perl
# @(#) p2 Demonstrate line-join within specific range.
use warnings;
use strict;
my ($debug);
$debug = 0;
$debug = 1;
my ($in_sequence) = 0;
while (<>) {
if ( /[(]NP/ .. /[)]$/ ) {
$in_sequence++;
chomp;
print "$_ ";
next;
}
elsif ($in_sequence) {
$in_sequence = 0;
print "\n";
}
print;
}
exit(0);
Assuming data is on file "data1", the script then produces:
% ./p2 data1
line 1
line 2
(NP line 3 line 4 line 5)
line 6
The parentheses are special in the matching operation, so we escape them. One way is to precede them with a backslash, but some people like readability of single characters in square brackets.
We go through the file and whenever we are in the appropriate range, we print the line without the newline, and move onto the next line. If outside, we check to see if we have completed a join, and if so, print a newline, print the current line in any case, and loop. There is also a triple-dot operator, research on which is left as an exercise for the reader.
$
$ cat f1
line 1
line 2
(NP
line 3
line 4
line 5)
line 6
$
$
$ ##
$ perl -ne 'BEGIN{$x=0} chomp;
> if (/^\(/){$x=1; $c=1}
> elsif (/\)$/){$x=0; $c=0}
> elsif ($x==1){$c=1}
> else {$c=0}
> if ($c == 1) {printf("%s ", $_)}
> else {printf("%s\n", $_)}' f1
line 1
line 2
(NP line 3 line 4 line 5)
line 6
$
$
local $/="";
my $str=<DATA>;
$str=~s/\n(?=([^\(\n]*\n*)*\))/ /g;
print $str;
__DATA__
line 1
line 2
(NP
line 3
line 4
line 5)
line 6
(
line 7
line 8
)
line 9