ye-ti-800
ye-ti-800

Reputation: 218

Perl: read file and re-arrange into columns

I have a file that i want to read in which has the following structure:

EDIT: i made the example a bit more specific to clarify what i need

HEADER
MORE HEADER
POINTS 2 
x1 y1 z1
x2 y2 z2
VECTORS velocities
u1 v1 w1
u2 v2 w2
VECTORS displacements
a1 b1 c1
a2 b2 c2

The number of blocks containing some data is arbitrary, so is their order.
i want to read only data under "POINTS" and under "VECTORS displacements" and rearrange them in the following format:

x1 y1 z1 a1 b1 c1
x2 y2 z2 a2 b2 c2

I manage to read the xyz and abc blocks into separate arrays but my problem is to combine them into one.

I should mention that i am a perl newbie. Can somebody help me?

Upvotes: 0

Views: 149

Answers (2)

Borodin
Borodin

Reputation: 126722

This is made very simple using the range operator. The expression

/DATA-TO-READ/ .. /DATA-NOT-TO-READ/

evaluates to 1 on the first line of the range (the DATA-TO-READ line), 2 on the second etc. On the last line (the DATA-NOT-TO-READ line) E0 is appended to the count so that it evaluates to the same numeric value but can also be tested for being the last line. On lines outside the range it evaluates to a false value.

This program accumulates the data in array @output and prints it when the end of the input is reached. It expects the path to the input file as a parameter on the command line.

use strict;
use warnings;

my (@output, $i);

while (<>) {
  my $index = /DATA-TO-READ/ .. /DATA-NOT-TO-READ/;
  if ($index and $index > 1 and $index !~ /E/) {
    push @{ $output[$index-2] }, split;
  }
}

print "@$_\n" for @output;

output

x1 y1 z1 a1 b1 c1
x2 y2 z2 a2 b2 c2

Upvotes: 1

choroba
choroba

Reputation: 241768

I only used 1 array to remember the first 3 columns. You can output directly when processing the second part of the data.

#!/usr/bin/perl
use strict;
use warnings;

my @first;                                  # To store the first 3 columns.
my $reading;                                # Flag: are we reading the data?
while (<>) {
    next unless $reading or /DATA-TO-READ/; # Skip the header.

    $reading = 1, next unless $reading;     # Skip the DATA-TO-READ line, enter the
                                            # reading mode.
    last if /DATA-NOT-TO-READ/;             # End of the first part.

    chomp;                                  # Remove a newline.
    push @first, $_;                        # Remember the line.
}

undef $reading;                             # Restore the flag.
while (<>) {
    next unless $reading or /DATA-TO-READ/;

    $reading = 1, next unless $reading;
    last if /DATA-NOT-TO-READ/;

    print shift @first, " $_";              # Print the remembered columns + current line.
}

Upvotes: 1

Related Questions