Using Raku (formerly known as Perl_6)
raku -e 'my @a = lines>>.split(","); my $m = @a>>.elems.max; \
.flat.join(",").put for [Z] @a>>.[0..$m-2], ("", @a>>.[$m-1]).flat;'
raku -e 'my @a = lines.map: *.split(","); my $m = @a.map(*.elems).max; \
.flat.join(",").put for [Z] @a.map(*.[0..$m-2]), ("", @a.map: *.[$m-1]).flat;'
This Raku answer is a little longer but is also more of a general solution, since the number of columns per row isn't hard-coded: a file-wide
max is computed.
Briefly (both examples),
lines are read-in, each
, commas, and stored in
@a array. A
max number of
elems (columns) is computed and stored as
$m. Then Raku's
[Z] "Zip Reduction" operator is used to pull off elements from the two lists that follow it one-by-one: these elements are
joined back together in the out
put, such that now a
"" empty string occupies the end of the first row, and subsequent
@a[$m-1] indexed-values are moved down a row. Nota bene: Raku doesn't auto-flatten array elements, so you have to
flatten them manually (if desired).
In the two examples I've tried to show how Raku's
>> "hyper"-operator is similar to
mapping a function/index over individual elements, either
.map(*.fn) or (at the end of a method chain) using the colon form
.map: *.fn;, which can reduce the number of parens required.
Addendum: Here's another Raku approach, this time unwrapping the row/columns into individual elements, and reconstructing with
rotor. It gives the exact same result as above:
raku -e 'my @a = lines>>.split(",").flat; my @b = @a[3,7,11...*]; \
@a.=rotor(3 => 1); @a.=map(*.join(",")); @b.=unshift(""); \
.join(",").put for [Z] @a, @b;'