Using Raku (formerly known as Perl_6)
~$ raku -e 'my @a = slurp.comb( / "======" (<alpha>**3) "======" \v [ \V+ \v]+? <?before "======" | $ > /); \
.print for flat @a[0..1,(2..3).sort.reverse,4..*];' file
OR:
~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v }; \
my @a = slurp.comb( / <H> [ \V+ \v ]+? <?before <H> | $ > /); \
.print for flat @a[0..1,(2..3).sort.reverse,4..*]' file
Above are solutions coded in Raku, a member of the Perl-family of programming languages. Raku features a comb function, which lets you declare a repeating pattern that you're seeking in your file (as opposed to split, which declares and usually destroys a separator between desired elements). Both solutions use Raku's slurp function, which reads the entire file into memory (without breaking on newlines).
NOTE: When re-arranging [ … ] indices within an @-sigiled array, it is very important to flatten the resulting sequence and/or object, since Raku (unlike Perl) does not auto-flatten by default.
In the first solution, the header line
"======" (<alpha>**3) "======" \vis sought, followed by the body pattern[ \V+ \v ]+?. Here\vis the built-in vertical-whitespace character class, and\Vis the built-in non- vertical-whitespace character class. The?makes the match non-greedy (i.e. frugal). The\V+means there has to be at least one body line (change to\V*if zero-body lines is acceptable).In the second solution, the header line pattern is abstracted out into its own
Hregex pattern. So the followingcombcall can use<H>within the/…/matcher to search for the header pattern. You can make this pattern as simple as you wish (i.e."======"), or adapt it to other files, etc. So this code can become quite a general solution.
Sample Input:
======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======jkl======
data7
======mno======
data8
Sample Output:
======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8
Raku has some helpful features one of which is being able to use the built-in pairs function. A second useful feature is calling raku on an object, to get back Raku's internal representation of data. Combining with Raku's put call (print using \n newline terminator):
~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v }; \
my @a = slurp.comb( / <H> [ \V+ \v]+? <?before <H> | $ > /).pairs; \
.raku.put for flat @a[0..1,(2..3).sort.reverse,4..*];' file
0 => "======abc======\ndata1\ndata2\ndata3\n"
1 => "======def======\ndata4\n"
3 => "======jkl======\ndata7\n"
2 => "======ghi======\ndata5\ndata6\n"
4 => "======mno======\ndata8\n"