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

I've taken a look at this node and it's just not making sense when I try to apply it to my problem.

I have text in a file like this:

checking image file <NT-Development_1024371283_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does not exist >copy 1 frag 2 media CC0202 host netbackup2: media does not exist >copy 1 frag 3 media CC0202 host netbackup2: media does not exist >copy 1 frag 4 media CC0202 host netbackup2: media does not exist >copy 1 frag 5 media CC0202 host netbackup2: media does not exist checking files file <NT-Development_1024371283_FULL.f>
What I need to do is check for the existence of "media does not exist" between:
checking image file <NT-Development_1024371283_FULL>
and
checking files file <NT-Development_1024371283_FULL.f>
and populate a variable with "NT-Development_1024371283_FULL" for later use.

Any help, as always, is appreciated.

Replies are listed 'Best First'.
Re: How to act upon lines between two other lines in file?
by tall_man (Parson) on Feb 09, 2003 at 02:43 UTC
    Your problem seems similar to one answered by tachyon in Re: Formatting questions. His example code slurps in all the lines from the file at once and then splits on the leading pattern, something like this:
    use strict; undef $/; my $data = <>; my @data = split 'checking', $data; shift @data; my @bad_files; for my $bit (@data) { my ($file_name) = $bit =~ /file <([^>]+)>/; push @bad_files, $file_name if ($bit =~ /media does not exist/); }
Re: How to act upon lines between two other lines in file?
by zengargoyle (Deacon) on Feb 09, 2003 at 03:09 UTC

    how about something like this...

    #!/usr/bin/perl use strict; use warnings; my $current; my %data; my $ok; while (<DATA>) { next unless ( /^checking image file/ ... /^checking files file +/ ); if ( /^checking image file <(.*?)>$/ ) { # first line match $current = $1; $ok = 1; # set our file and + status next; } if ( /media does not exist/ ) { # a bad line $ok = 0; next; } if ( /^checking files file/ ) { # last line match $data{$current} = $ok ? "ok" : "bad"; } } END { foreach my $k (sort keys %data) { print "$k is $data{$k}$/"; } } __DATA__ checking image file <NT-Development_1024371283_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does not exist >copy 1 frag 2 media CC0202 host netbackup2: media does not exist >copy 1 frag 3 media CC0202 host netbackup2: media does not exist >copy 1 frag 4 media CC0202 host netbackup2: media does not exist >copy 1 frag 5 media CC0202 host netbackup2: media does not exist checking files file <NT-Development_1024371283_FULL.f> checking image file <NT-Development_1024371284_FULL> >copy 1 frag 1 media CC0202 host netbackup3: ok >copy 1 frag 2 media CC0202 host netbackup3: ok >copy 1 frag 3 media CC0202 host netbackup3: ok >copy 1 frag 4 media CC0202 host netbackup3: ok >copy 1 frag 5 media CC0202 host netbackup3: ok checking files file <NT-Development_1024371284_FULL.f> checking image file <NT-Development_1024371285_FULL> >copy 1 frag 1 media CC0205 host netbackup4: media does not exist >copy 1 frag 2 media CC0205 host netbackup4: media does not exist >copy 1 frag 3 media CC0205 host netbackup4: media does not exist >copy 1 frag 4 media CC0205 host netbackup4: media does not exist >copy 1 frag 5 media CC0205 host netbackup4: media does not exist checking files file <NT-Development_1024371285_FULL.f>
    $ ./test.pl
    NT-Development_1024371283_FULL is bad
    NT-Development_1024371284_FULL is ok
    NT-Development_1024371285_FULL is bad
    
Re: How to act upon lines between two other lines in file?
by Enlil (Parson) on Feb 09, 2003 at 03:11 UTC
    This is along the same lines as the other posts above. But more along the style I think you were asking for. (as noted by the node in your question. Anyhow, as the above it assumes that the checking image file lines come in pairs and that the only difference is the .f in the latter in the pair. It also assumes that media does not exist is the last thing on the line. Anyhow here is the code (Data tested with after __DATA__ and results after __END__ ):
    use strict; use warnings; my @records; my $media_existance = "Media does exist"; my $temp1 = 0; while ( <DATA> ) { if ( /^checking image file <(.*)>/ .. /(.*<$temp1\.f>)/ ) { $temp1 = $1; if ( $temp1 =~ /^checking/ ) { push @records, [$temp1,$media_existance]; $media_existance = "Media does exist"; } elsif ( /media does not exist$/ ) { $media_existance = "Media doe +s not exist" } } } foreach (@records) { print join ":",@$_; print $/; } __DATA__ checking image file <NT-Development_1024371281_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does not exist >copy 1 frag 2 media CC0202 host netbackup2: media does not exist >copy 1 frag 3 media CC0202 host netbackup2: media does not exist >copy 1 frag 4 media CC0202 host netbackup2: media does not exist >copy 1 frag 5 media CC0202 host netbackup2: media does not exist checking files file <NT-Development_1024371281_FULL.f> checking image file <NT-Development_1024371282_FULL> checking files file <NT-Development_1024371282_FULL.f> checking image file <NT-Development_1024371283_FULL> checking files file <NT-Development_1024371283_FULL.f> checking image file <NT-Development_1024371284_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does exist >copy 1 frag 2 media CC0202 host netbackup2: media does exist >copy 1 frag 3 media CC0202 host netbackup2: media does not exist >copy 1 frag 4 media CC0202 host netbackup2: media does exist >copy 1 frag 5 media CC0202 host netbackup2: media does exist checking files file <NT-Development_1024371284_FULL.f> checking image file <NT-Development_1024371285_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does exist >copy 1 frag 2 media CC0202 host netbackup2: media does exist >copy 1 frag 3 media CC0202 host netbackup2: media does exist >copy 1 frag 4 media CC0202 host netbackup2: media does exist >copy 1 frag 5 media CC0202 host netbackup2: media does exist checking files file <NT-Development_1024371285_FULL.f> checking image file <NT-Development_1024371286_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does not exist >copy 1 frag 2 media CC0202 host netbackup2: media does exist >copy 1 frag 3 media CC0202 host netbackup2: media does exist >copy 1 frag 4 media CC0202 host netbackup2: media does exist >copy 1 frag 5 media CC0202 host netbackup2: media does exist checking files file <NT-Development_1024371286_FULL.f> __END__ checking files file <NT-Development_1024371281_FULL.f>:Media does not +exist checking files file <NT-Development_1024371282_FULL.f>:Media does exis +t checking files file <NT-Development_1024371283_FULL.f>:Media does exis +t checking files file <NT-Development_1024371284_FULL.f>:Media does not +exist checking files file <NT-Development_1024371285_FULL.f>:Media does exis +t checking files file <NT-Development_1024371286_FULL.f>:Media does not +exist

    -enlil

Re: How to act upon lines between two other lines in file?
by BrowserUk (Patriarch) on Feb 09, 2003 at 05:48 UTC

    A somewhat different approach to the problem--it strikes a balance between slurping the file and processing it line by line--setting $/ as a 'boundary marker' and using -n to take care of the file handling. You just attach your code at the bottom and process the %ids hash as you need to.

    Caveats: It doesn't validate the format of the input file by cross-checking the end of block with the start. Testing is minimal in the absence of more information regarding the file format/content, and there are too many possible variations to try and guess.

    #! perl -nslw use vars qw[%ids]; use strict; BEGIN{$/="\nchecking";} if ( m[<(NT-Development_\d{10}_FULL)>.*?(media does not exist)?\Z] +s ) { $ids{$1} = defined $2 ? 'missing' : 'ok'; } }{ #! terminate implied (perl -n) while loop and start continue block #! process hash here. print "$_ was $ids{$_}" for sort keys %ids;

    sample usage


    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

Re: How to act upon lines between two other lines in file?
by FoxtrotUniform (Prior) on Feb 09, 2003 at 02:46 UTC

    Please use [id|name]-style links rather than linking explicitly, to avoid logging people out when they follow your links.

    I'm going to assume that the delimiting lines are of the form:

    checking image file <[^>]+> ... checking image file <[^>]+\.f>

    In which case, you could do something like (untested):

    my $file = ""; { local $/ = undef; $file = <INFILE>; } my %failures = (); while(my ($image, $msgs) = $file =~ /checking image file <([^>]+)> (.+?media does not exist.+?) checking image file <$1\.f>/gsx) { $failures{$image} = 1; }

    The /g modifier makes the regex start right after the last successful match on every iteration of the while loop, so you go through the input all the way, rather than matching the first occurrance all the time.

    This could be substantially prettier; I'm a bit sleep-deprived at the moment. Hopefully, though, it'll get you somewhere.

    --
    F o x t r o t U n i f o r m
    Found a typo in this node? /msg me
    The hell with paco, vote for Erudil!

Re: How to act upon lines between two other lines in file?
by pg (Canon) on Feb 09, 2003 at 02:46 UTC
    Following code assumes that "checking image ..." always matches "checking files" in pair, no checking for this:
    use strict; use Data::Dumper; open(FILE, "<", "file.txt"); my $active_file; my %files_with_bad_media; while (<FILE>) { if (m/^checking image file <(.*?)>/) { $active_file = $1; } elsif (m/checking files file/) { $active_file = undef; } else { if (m/media does not exist/) { if (defined($active_file)) { $files_with_bad_media{$active_file} = 1; } } } } close(FILE); print Dumper(\%files_with_bad_media);
Re: How to act upon lines between two other lines in file?
by dash2 (Hermit) on Feb 10, 2003 at 09:24 UTC
    TMTOWTDI:

    #!/usr/bin/perl -w my %bad; while (<DATA>) { if (/checking image file \<(NT-Development_\d+_FULL)\>/) { my $file = $1; # in case you ever change the regex below to ha +ve brackets do { $_ = <DATA>; $bad{$file}++ if /media does not exist/; } until /checking files file/; } } print join "\n", keys %bad; __DATA__ checking image file <NT-Development_1024371283_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does not exist >copy 1 frag 2 media CC0202 host netbackup2: media does not exist >copy 1 frag 3 media CC0202 host netbackup2: media does not exist >copy 1 frag 4 media CC0202 host netbackup2: media does not exist >copy 1 frag 5 media CC0202 host netbackup2: media does not exist checking files file <NT-Development_1024371283_FULL.f> checking image file <NT-Development_1026371283_FULL> checking files file checking image file <NT-Development_10243744283_FULL> >copy 1 frag 1 media CC0202 host netbackup2: media does not exist >copy 1 frag 2 media CC0202 host netbackup2: media does not exist checking files file <NT-Development_1024374483_FULL.f> __END__

    dave hj~