I hope you are not allergic to perl...
This solution will work for files with any number of columns:
$ perl -ne 'BEGIN { @a = (); } $i = 0; foreach (split(/\s+/)) { $l = ($a[$i++] ||= []); push @$l, $_; }; END { print join("\n", @$_) . "\n" foreach (@a); }' << EOF
> x1 y1 z1
> x2 y2 z2
> x3 y3 z3
> x4 y4 z4
> EOF
x1
x2
x3
x4
y1
y2
y3
y4
z1
z2
z3
z4
I'll comment since this is not really obvious:
perl -n
reads line by line (to be precise, it reads and splits against $/
), and -e
executes a scriptlet;
- the
BEGIN
block is executed before the first input is read, the END
block is executed last.
Anatomy:
BEGIN { @a = (); } # Creates an array named "a"
# Main scriptlet
$i = 0;
foreach (split(/\s+/)) { # Split an input line against one or more space chars
$l = # Set $l to...
($a[$i++] ||= []); # what is at index i of @a (increment i), but if not set,
# set to an (empty) array ref and return that
push @$l, $_; # Push token to the end of the array ref
}
END { # End block...
print join("\n", @$_) # Print the contents of array references, joined with \n,
. "\n" # then \n,
foreach (@a); # for each element of array a
} # DONE