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

#!/usr/bin/perl my $flag; while(<DATA>){ if (/^({\w+})/) { $flag = $1; } elsif ($flag =~ m/{TAG}/){ print $_; } elsif ($flag =~ m/{ID}/){ print $_; } } __DATA__ {IT} 343 1 {DATE} 090104 {LINE} LEGISLATORS VISIT SENIOR APARTMENT COMPLEX {TAG} 1lutherridge0104.ART {ID} 234 {IT} 434 2 {DATE} 090104 {LINE} LEGISLATORS VISIT SENIOR APARTMENT COMPLEX
{IT} is the start of one file. How to print the {IT} line if both {LINE} and {ID} doesn't exists.

Replies are listed 'Best First'.
Re: print line
by GrandFather (Saint) on Nov 25, 2009 at 06:53 UTC

    If I've understood what you want to achieve (showing the output you expect would help), the following may do the trick:

    use strict; use warnings; my %tags; my $printing; while (defined (my $line = <DATA>) || defined $tags{IT}) { if (defined $line) { my ($tag) = $line =~ /^{(\w+)}/; if (! $tag) { print $line if $printing; next; } $printing = $tag =~ /^(TAG|ID)$/; if ($tag ne 'IT') { ++$tags{$tag}; next; } } print $tags{IT} if (! $tags{LINE} || ! $tags{ID}) && defined $tags{IT}; %tags = (IT => $line); } __DATA__ {IT} 343 1 {DATE} 090104 {LINE} LEGISLATORS VISIT SENIOR APARTMENT COMPLEX {TAG} 1lutherridge0104.ART {ID} 234 {IT} 434 2 {DATE} 090104 {LINE} LEGISLATORS VISIT SENIOR APARTMENT COMPLEX

    Prints:

    1lutherridge0104.ART 234 {IT} 434

    The key is to 'remember' what has been seen and perform the extra processing when the next section is detected. Note the tricky stuff that gets the last section handled correctly when the end of file is reached.


    True laziness is hard work
Re: print line
by chromatic (Archbishop) on Nov 25, 2009 at 06:52 UTC

    Set the input record separator ($/) to {ID}. Then you can read a record at a time and split the record into hash keys and values. It's trivial to print specific values on the existence or absence of other keys.

Re: print line
by Khen1950fx (Canon) on Nov 25, 2009 at 06:53 UTC
    If I understand you correctly, then you could do this:

    my $flag; while ( defined( $_ = <DATA> ) ) { if (/^({\w+})/) { $flag = $1; } elsif ( $flag =~ /{IT}/ ) { print $_; } elsif ( $flag =~ /{TAG}/ ) { print $_; } elsif ( $flag =~ /{ID}/ ) { print $_; } } __DATA__ {IT} 343 1 {DATE} 090104 {TAG} 1lutherridge0104.ART {IT} 434 2 {DATE} 090104
Re: print line
by bichonfrise74 (Vicar) on Nov 25, 2009 at 22:02 UTC
    Can you try to use this?
    #!/usr/bin/perl use strict; local $/ = '{IT}'; while (my $line = <DATA>) { my ($it) = $line =~ /(^\s\d+)/; print "{IT}$it\n" if ! ( $line =~ /{LINE}/ && $line =~ /{IT}/ ) && ( defined( $it) ); } __DATA__ {IT} 343 1 {DATE} 090104 {LINE} LEGISLATORS VISIT SENIOR APARTMENT COMPLEX {TAG} 1lutherridge0104.ART {ID} 234 {IT} 434 2 {DATE} 090104 {LINE} LEGISLATORS VISIT SENIOR APARTMENT COMPLEX