charles hendry
charles hendry

Reputation: 1740

Reading two lines of data from a file

I have a file which I would like to read data from. This is a sample of the data:

NODELOAD         28     27132    3.29108E+04    7.94536E+04    0.00000E+00
NODELOAD         29     27083    9.89950E+04    9.89950E+04    0.00000E+00
NODELOAD         29     27132    6.08112E+04    6.08112E+04    0.00000E+00
NODELOAD         30     27083    1.29343E+05    5.35757E+04    0.00000E+00
NODELOAD         30     27132    7.94536E+04    3.29108E+04    0.00000E+00
NODELOAD         31        68    4.80185E+04   -5.47647E+04   -1.17033E+04
                                -1.27646E+03    1.18350E+04   -2.03885E+03
NODELOAD         31      1114    1.20706E+05   -3.31323E+04   -7.17280E+04
                                 2.28198E+03    2.75582E+04    5.74460E+02

I have this code and am able to read all values of a single line and save them to an array:

  foreach my $line (@input) {
    if($line =~ /^\s*NODELOAD\s+/i) {
      $line =~ s/^\s*//;
      @a = split(/\s+/,$line);

      $modelData{"NODELOAD"}->{$a[1]}->{$a[2]}->{"Fx"} = $a[3];
      $modelData{"NODELOAD"}->{$a[1]}->{$a[2]}->{"Fy"} = $a[4];
      $modelData{"NODELOAD"}->{$a[1]}->{$a[2]}->{"Fz"} = $a[5];

However, there are some "NODELOAD" definitions in the file that are defined on two lines and have 6 load values instead of 3 (the first two numbers on each line are identifiers, the following 3/6 are data).

Is it easiest writing an if statement, which saves the data if the following line does not begin with "NODELOAD" and contains numbers? The very last line after this part in the text file will not contain any numbers, but may be blank or contain text.

Upvotes: 1

Views: 510

Answers (1)

kompas
kompas

Reputation: 425

Yes, the easiest approach would be to keep values from previous call in some variable, then if if(/NODELOAD/) doesn't match, you get just 3 values and process them using identifiers from previous line (and previous look iteration). You could also skip a regexp in if, and check for the first element of split result:

my @last_values;
foreach my $line (@input) {
    $line =~ s/^\s+//;
    my @values = split(/\s+/, $line);
    if( $values[0] ne 'NODELOAD' ) {
        unshift( @values, @last_values[0..2] ); # Get first 3 values from previous call
        # Then process it however you'd like to
        $modelData{"NODELOAD"}->{$values[1]}->{$values[2]}->{"Fx2"} = $values[3];
    }
    elsif {
        # process like previously...
        $modelData{"NODELOAD"}->{$values[1]}->{$values[2]}->{"Fx"} = $values[3];
        $modelData{"NODELOAD"}->{$values[1]}->{$values[2]}->{"Fy"} = $values[4];
        $modelData{"NODELOAD"}->{$values[1]}->{$values[2]}->{"Fz"} = $values[5];
        @last_values = @values; # and save for future reference
    }
 }

Upvotes: 1

Related Questions