Skip to main content
5 of 6
add second `flat`tening method (via Bruce Gray)
jubilatious1
  • 3.9k
  • 10
  • 21

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) "======" \v is sought, followed by the body pattern [ \V+ \v ]+?. Here \v is the built-in vertical-whitespace character class, and \V is 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 H regex pattern. So the following comb call 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"

#OR (another way of flattening):

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v]+? <?before <H> | $ > /).pairs;  \
            .raku.put for @a[flat(0..1;(2..3).sort.reverse;[email protected])];'  file
0 => "======abc======\ndata1\ndata2\ndata3\n"
1 => "======def======\ndata4\n"
3 => "======jkl======\ndata7\n"
2 => "======ghi======\ndata5\ndata6\n"
4 => "======mno======\ndata8\n"

https://docs.raku.org
https://raku.org

jubilatious1
  • 3.9k
  • 10
  • 21