Here is a sed
solution that will string together any sequence of the ,,$
lines following the last occurring ^1
line:
sed -e '/^1/{x;s/\n/ /gp;d' -e '};/,,$/H;$G;D
' <<\IN
1, p1, p2, p3, p4, p5, p6, p7
2, p9, p10,,
2, q1, q2, q3, q4, q5, q6, q7
2, q9, q10,,
2, r1, r2, r3, r4, r5, r6, r7
2, r9, r10,,
1, s1, s2, s3, s4, s5, s6, s7
2, s9, s10,,
IN
It ex
changes h
old and pattern spaces on lines that begin with a ^1
and s///p
rints whatever the contents of h
old space was previous to that only in the event of a successful substitution. Lines ending with ,,$
are appended to H
old space following a \n
ewline character and then all lines are D
eleted up to the first occurring \n
ewline character. On the $
last line H
old space is appended to pattern space following a \n
ewline - so when it is D
eleted it restarts the line cycle at the top of the script containing only what H
old space contained - which gets it printed as necessary.
OUTPUT:
1, p1, p2, p3, p4, p5, p6, p7 2, p9, p10,, 2, q9, q10,, 2, r9, r10,,
1, s1, s2, s3, s4, s5, s6, s7 2, s9, s10,,
If, on the other hand, you do not want the subsequent /,,$/
occurrences then this might do:
sed -e '/^1/{x;y/\n/ /;s/,,.*/,,/p;d' -e '};/,,$/H;$G;D'
Given the same input that prints instead:
1, p1, p2, p3, p4, p5, p6, p7 2, p9, p10,,
1, s1, s2, s3, s4, s5, s6, s7 2, s9, s10,,
But that will get /,,$/
lines printed even if they do not immediately follow a /^1/
match. If you want the pairs only if they are immediately sequential in input - you can do that as well:
sed -n '/^1/!d;$p;N;/\n1/P;/,,$/s/\n/ /p;D'
That works thus:
- It first
d
eletes from output all lines which do !
not begin with /^1/
- This includes lines brought in with
N
that do not end with /,,$/
.
- If the this is the
$
last input line pattern space is here p
rinted, because the next command will end the script.
- On
/^1/
matches it appends the N
ext input line to pattern space following a \n
ewline character.
- If the appended line also begins with a
/\n1/
it P
rints the previous.
P
prints only up to the first occurring \n
ewline in pattern space.
- After pulling in the
N
ext input line if pattern space $
ends with a /,,$/
match it s///
ubstitutes a space character for the inserted \n
ewline character and p
rints the results.
- Pattern space is always
D
eleted up to and including the first occurring \n
ewline character.
- ...so when a
N
ext input line doesn't match /,,$/
it is sent back to the top of the script as the head of the line. If at that point it does not match ^1
it is d
eleted completely.
- ...because
/,,$/
have already had their \n
ewline completely removed by this point, they are removed from flow comletely here.
All of this means that if /^1/
lines follow one another they are still printed, and if lines which do not end in ,,$
follow a ^1
they are not printed.