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

Hello hoping someone could help me. I am trying to create a script which searches through all files in a directory for a string, if the string is found I want it to look through the entire file which it found the first string and look for a second string. Right now I have the code below, but it looks like when it tries to match the second string it's comparing the regex against the result/output of the first regex not against the entire file which it found the fist regex in. How can I make my script search for a string against a file if it finds the string in that file then search that entire file once again for the second string. thanks for the help.
<code> sub edits() { if ( -f and /^Khlog.08$/ ) { foreach ( $File::Find::name ) { open(LOG, "< $File::Find::name") or die "Could not open fi +le $_: $!"; while ( <LOG> ) { my $LINE = $_; if ( $LINE =~ m/002389983/ ) { print "Looking for: 002389983\n Found it in file: +$LINE\n"; if ( $LINE =~ m/29994339499/ ) { print "Looking for: 29994339499\n Found it in +file: $LINE\n"; } else { print "Could not find the second string: 29994 +339499\n"; } } } } }

Replies are listed 'Best First'.
Re: How to search for two strings/regex in one file
by JavaFan (Canon) on Dec 01, 2008 at 21:14 UTC
    Personally, I wouldn't reinvent the wheel. I'd use a shell one-liner, something like:
    grep -l 002389983 * | xargs grep -l 29994339499
    (You may wish to tweak this if you've file names with newlines)

    Anyway, your code only checks if a line matches against both patterns, not a file. You'll have to rewind your file and check each line again with the second regexp. Or just check each line twice. Something like:

    open my $fh, "<", $File::Find::name or die; my ($f1, $f2); while (<$fh>) { $f1 ||= /02389983/; $f2 ||= /29994339499/; last if $f1 && $f2; } if ($f1 && $f2) { ... Both patterns found ... }
Re: How to search for two strings/regex in one file
by kyle (Abbot) on Dec 01, 2008 at 21:23 UTC

    You want to read the file only once and look for both strings. You don't care whether the second is found when the first is not found, but it's probably cheaper to look for both from the beginning rather than go back and reread the file when it's time to look for the second string.

    What you're doing right now is looking for the second string only on lines that contain the first string.

    sub edits { return if ! -f; return if ! /^Khlog.08$/; open my $log_fh, '<', $_ or die "Can't read '$File::Find::name': $!"; my ( $found1, $found2 ); while ( defined( my $line = <$log_fh> ) ) { $found1 = $found1 || ( $line =~ /002389983/ ); $found2 = $found2 || ( $line =~ /29994339499/ ); last if $found1 && $found2; } }
Re: How to search for two strings/regex in one file
by toolic (Bishop) on Dec 01, 2008 at 21:14 UTC
    Your code will only find the 2nd string if it is on the same line as the 1st string: foo 002389983 blah 29994339499

    Stop looking through the file as soon as the 1st string is found. If the 1st string is found, start looking through the file from the beginning again. Stop looking through the file as soon as the 2nd string is found. Untested:

    my $found_first = 0; my $found_second = 0; while (<LOG>) { if (/002389983/) { print "Looking for: 002389983\n Found it in file: $_\n"; $found_first = 1; last; } } if ($found_first) { seek LOG, 0, 0; while (<LOG>) { if (/002389983/) { print "Looking for: 29994339499\n Found it in file: $_\n"; $found_second = 1; last; } } } unless ($found_second) { print "Could not find the second string: 29994339499\n"; }
Re: How to search for two strings/regex in one file
by zentara (Cardinal) on Dec 01, 2008 at 21:17 UTC
    seek LOG 0,0;
    will reset your LOG filehandle to the top, but you may need to adjust your nested if loops. Some pseudocode(untested)
    while ( <LOG> ) { my $LINE = $_; if ( $LINE =~ m/002389983/ ) { print "Looking for: 002389983\n Found it in file: $LINE\n"; last; } } seek LOG, 0, 0; while ( <LOG> ) { if ( $LINE =~ m/29994339499/ ) { print "Looking for: 29994339499\n Found it in file: $LINE\n"; }else { print "Could not find the second string: 29994339499\n"; } }

    I'm not really a human, but I play one on earth Remember How Lucky You Are