Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I need to append the next line in a file to the current line if the date is the same. Here is my current code:

foreach $line (@data) { if ( ($line =~ /*disregard this*/)) { # If nextline date = previous line date # Append next line to current line # Else append the value 0
Data is here: Wed,Jun,13,10:40:35,2012 Wed,Jun,13,10:40:35,2012

My apologies for lack of code, but I am looking for a concept more than anything. Thank you.

Replies are listed 'Best First'.
Re: Append Next Line To Current Line
by daxim (Curate) on Jul 02, 2012 at 17:07 UTC
    1. Read a line $current until exhausted.
    2. Compare with previous line $previous.
      1. If equal, append.
      2. If not equal, do nothing.
    3. Output.
    4. Move $current to $previous.
    5. Go to 1.
Re: Append Next Line To Current Line
by Ransom (Beadle) on Jul 02, 2012 at 17:10 UTC

    Implement those comments and it should work. What sort of concept are you looking for?

    Most likely you'll just need to store the previous line date and check it against the current line date. You won't have access to the next line date unless you look ahead or process behind.

    Try out the idea you have and let us know how it goes. With more specific (actual) code, we can give you more actual responses.

    Are you able to implement your idea and just looking for another way to do it, or do you need help with implementation?

      I should have posted more code. Here is my complete code:

      open(FH, "error_log:); @data = <FH> foreach $line (@data) { if ( ($line =~ /notice/)) { $line =~ s/ /,/g; my @L1 = split(/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy, +|rd,|wr,|ka,|log,|dns,|cls,|bsy:,|in,|/, $line); $line =~ s/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy,|rd,| +wr,|ka,|log,|dns,|cls,|bsy:,|in,//g; print $line;

      Note that I printed only to see the output. Output is the following:

      Wed,Jun,13,10:40:35,2012,758,42,0,29,11,0,0,2 Wed,Jun,13,10:40:35,2012,29,mod_was_ap22_http.c Wed,Jun,13,10:41:35,2012,761,39,0,34,5,0,0,0 Wed,Jun,13,10:41:35,2012,34,mod_was_ap22_http.c Wed,Jun,13,10:42:35,2012,769,31,0,22,6,0,0,3 Wed,Jun,13,10:42:35,2012,22,mod_was_ap22_http.c Wed,Jun,13,10:43:35,2012,754,46,0,29,17,0,0,0

      I would like the number (42) placed in csv form after the others on the first line corresponding to the timestamp. If the line has nothing below (ex. last line) I would like to input a zero. Thank you for your help.

        First we're going to need access to previous/next lines. Instead of a foreach loop, try out a for loop so we can use index numbers on the @data array. The following snippet should get you started. Basically you now have two lines of data per each loop which will allow you to compare and append data from both.

        open(FH, "error_log"); @data = <FH> for (my $index = 0; $index < $data; $index++) { my $line = @data[$index]; my $nextline = @data[$index + 1] if ($index < $data - 1); if ( ($line =~ /notice/)) { #format line $line =~ s/ /,/g; my @L1 = split(/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy, +|rd,|wr,|ka,|log,|dns,|cls,|bsy:,|in,|/, $line); $line =~ s/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy,|rd,| +wr,|ka,|log,|dns,|cls,|bsy:,|in,//g; print $line; #format nextline $nextline =~ s/ /,/g; my @L1 = split(/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy, +|rd,|wr,|ka,|log,|dns,|cls,|bsy:,|in,|/, $nextline); $nextline =~ s/|notice|\[|\]|,mpmstats:,|\t|rdy,|bsy,| +rd,|wr,|ka,|log,|dns,|cls,|bsy:,|in,//g; print $nextline; }

        You'll need to take care of the ending situation (when $index is the last element of @data). I'm not entirely positive what your regex is doing, but I'm assuming that's where data is getting put into a csv format? You'll need to get at the innards of the line in order to append data from it. Hope this helps some, keep posting if you need to.

        My mistake: The number is not 42 it would be 29 for the first line.

Re: Append Next Line To Current Line
by Jim (Curate) on Jul 02, 2012 at 18:19 UTC

    Rename the array variable @data to @lines for the sake of clarity.

    Alternatively, don't slurp the entire file into an array in the first place. Simply process the file line by line, which is easily done in Perl.

    If you process the file line by line, then you'll need to delay printing every line until after you've read the next line and made whatever changes you need to make to the previous line:

    my $previous_line; LINE: while (my $line = <>) { next LINE if $line =~ m/disregard this line/; chomp $line; # Here's where you implement your algorithm # to compare the value on line $line with the # value on line $previous_line and print the # appropriate ouput line $previous_line = $line; } # Here's where you print the last line # modified as appropriate given that # there is no next line

    You asked for concepts, I gave you concepts.