Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

parsing array by individual element

Status
Not open for further replies.

czarj

Technical User
Apr 22, 2004
130
US
I have an array containing three variables. The "section" variable contains a number 1,2,3,4....n. Every n is part of the same transaction. I would like to parse the array by that (section) element. For example, I would like to create a subarray for every "63" that I could then print to a file or calculate lag time, ect.

The array contains data like this:
63 Jan 08 10:06:42 EST version: 4
63 Jan 08 10:06:42 EST version: 4
63 Jan 08 10:06:42 EST Text:
64 Jan 08 10:06:42 EST Text:
64 Jan 08 10:06:42 EST Text:
64 Jan 08 10:06:42 EST NDMP message type: NDMP_CONNECT_OPEN

$section= 63 or 64
$date = Jan 08 10:06:42 EST
$content = text strings


I was thinking just a simply foreach loop of the array would be a good start, but i'm not sure how to create an embedded array for the element.
Code:
while (<NDMPLOG>) {
   chomp;
   my($date,$section,$content)=split/[\[\]]/;
   $content=substr($content,2);
   $section=substr($section,6);
   @ndmpstuff = ($section,$date,$content);

foreach (@ndmpstuff)
  {
  }

}

Any help would be appreciated.
Thanks!

--- You must not fight too often with one enemy, or you will teach him all your tricks of war.
 
use the push() function to assign the data you want into the new array.

Code:
my @ndmpstuff;
while (<NDMPLOG>) {
   chomp;
   my($date,$section,$content)=split/[\[\]]/;
   $content=substr($content,2);
   $section=substr($section,6);
   push @ndmpstuff,[$section,$date,$content];
}

That makes an array of arrays, not sure if thats what you want or not.


------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I'm not sure push will do it. To be more explicit what I need to to process all variables in the array where $section=1. Then when that is done the foreach loop needs to process all variables in the array where $section=2...and so on.

For example here would be a sample output of what I'm trying to do. Each $section is printed with "\n" between them and the $date variable is used to calculate lag time.

----outputfile-----
Total Time: 8sec
63 Jan 08 10:06:42 EST test
63 Jan 08 10:06:42 EST output from test
63 Jan 08 10:06:48 EST Text:

Total Time: 20sec
64 Jan 08 10:06:42 EST more text
64 Jan 08 10:06:42 EST error, out of test
64 Jan 08 10:07:02 EST Text:

Total Time: 30sec
65 Jan 08 11:07:22 EST version: 343434
65 Jan 08 11:07:42 EST string me
65 Jan 08 11:07:42 EST Text:
65 Jan 08 11:07:42 EST version: 4
65 Jan 08 11:07:52 EST version: 44


Basically, how do I make this syntaxically correct?
Code:
foreach $section subset in (@ndmpstuff)
  {
  do stuff
  }

Thanks for the help!!!

--- You must not fight too often with one enemy, or you will teach him all your tricks of war.
 
Is the file in order by sections? If so you can step through the file, check the value of the section and keep processing the data for that section. When a new section comes up dump the data for the previous section to a file or array or whataver it is you are doing. If the file is not in order by sections that you can sort the data first before processing it. This is totally off the top of my head and untested but hopefully helps get you started:

Code:
use strict;
use warnings;

my $seen;
my @temp;

open(NDMPLOG, "filename") or die "$!";

# get the first line from the file to get started
my $first_line = <NDMPLOG>;
chomp ($first_line);
my($section,$date,$content) = split(/[\[\]]/,$first_line);
$seen = $section;

while (<NDMPLOG>) {
   chomp;
   my($section,$date,$content) = split(/[\[\]]/);
   if ($seen != $section) {
      $seen = $section;
      process(\@temp);
      @temp = ();
      redo;
   } 
   push @temp,[$section,$date,$content];
}
close NDMPLOG;

sub process {
   my ($temp) = @_;
   foreach my $line (@{$temp}) {
      # do your calculations. Keep in mind
      # this is an array of arrays.
   }
   print "The results of the calculations";
   return(0);
}

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Thanks Kevin. I took you code example and tried what is below. I am still having one problem however. Instead of looping through each "section id" it is continually printing one section over and over.

Code:
#### create global datastore variable
%DATASTORE = ();

#### parse the ndmp log into an array
while (<NDMPLOG>) {
   chomp;
   my($date,$section,$content)=split/[\[\]]/;
   $content=substr($content,2);
   $section=substr($section,6);

   push @{$DATASTORE{$section}}, "$section,$date,$content";

   foreach my $section (sort {$b <=> $a} keys %DATASTORE) {
      foreach my $entry (@{$DATASTORE{$section}}) {
        print PARSEFILE "$entry\n";
        }
      }

}

--- You must not fight too often with one enemy, or you will teach him all your tricks of war.
 
Don't understand why you are splitting on square brackets, as there are no such brackets in your data.
Anyway your choice of a hash of arrays is the correct one. What you need to do is to put the [tt]foreach[/tt] loop outside the [tt]while[/tt] : so you first parse the file into a hash of arrays, then you process the data in the hash.

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
Franco-

Thanks, I moved it outside the WHILE and it no longer runs in an infinite loop. However still one problem- with the code below I get the following output:

==============
63 Jan 08 10:06:42 EST Msgtype 1
==============
63 Jan 08 10:06:42 EST Method 2304
==============
63 Jan 08 10:06:42 EST ReplySequence 1
==============
64 Jan 08 12:20:31 EST Calling NdmpServer.kill
==============
64 Jan 08 12:20:31 EST Error code: NDMP_NO_ERR

However, I am after something more like this:
63 Jan 08 10:06:42 EST Msgtype 1
63 Jan 08 10:06:42 EST Method 2304
63 Jan 08 10:06:42 EST ReplySequence 1
==============
64 Jan 08 12:20:31 EST Calling NdmpServer.kill
64 Jan 08 12:20:31 EST Error code: NDMP_NO_ERR

I just wanted each $section key to be treated independently.

Code:
#### create and open the ouput file
open (PARSEFILE, ">$opt_o/ndmp.out");

#### create global datastore variable
%DATASTORE = ();

#### parse the ndmp log into an array
while (<NDMPLOG>) {
   chomp;
   my($date,$section,$content)=split/[\[\]]/;
   $content=substr($content,2);
   $section=substr($section,6);
   push @{$DATASTORE{$section}}, "$section $date $content";
}

#### process the array
foreach my $section (sort {$a <=> $b} keys %DATASTORE) {
   foreach my $entry (@{$DATASTORE{$section}}) {
        print PARSEFILE "$entry\n";
        print PARSEFILE "==============\n";
    }
}

Thanks,
Justin

--- You must not fight too often with one enemy, or you will teach him all your tricks of war.
 
Once again: move something out of the loop!
Code:
for my$section(sort{$a<=>$b}keys%DATASTORE){
  print PARSEFILE join"\n",@{$DATASTORE{$section}};
  print PARSEFILE "\n==============\n";
}
Oops! I also simplified the inner for loop, you can keep it as it was.
Also note, as a supplemental totally unimportant detail, that, if your sections are always with two figures (as your code above implies) you can also write
[tt]for my$section(sort keys%DATASTORE){[/tt]


Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
If the file is not in order by section then using the hash of arrays is the way to go. But if it is in order, the way I showed is the way to go.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top