user1782046
user1782046

Reputation: 13

Search string with multiple words in the pattern

My program is trying to search a string from multiple files in a directory. The code searches for single patterns like perl but fails to search a long string like Status Code 1.

Can you please let me know how to search for strings with multiple words?

#!/usr/bin/perl

my @list = `find /home/ad -type f -mtime -1`;

# printf("Lsit is $list[1]\n");

foreach (@list) {

    # print("Now is : $_");

    open(FILE, $_);
    $_ = <FILE>;
    close(FILE);

    unless ($_ =~ /perl/) { # works, but fails to find string "Status Code 1"
        print "found\n";

        my $filename = 'report.txt';
        open(my $fh, '>>', $filename) or die "Could not open file '$filename' $!";
        say $fh "My first report generated by perl";
        close $fh;

    } # end unless

} # end For

Upvotes: 0

Views: 149

Answers (3)

Borodin
Borodin

Reputation: 126762

There are a number of problems with your code

  • You must always use strict and use warnings at the top of every Perl program. There is little point in delcaring anything with my without strict in place

  • The lines returned by the find command will have a newline at the end which must be removed before Perl can find the files

  • You should use lexical file handles (my $fh instead of FILE) and the three-parameter form of open as you do with your output file

  • $_ = <FILE> reads only the first line of the file into $_

  • unless ($_ =~ /perl/) is inverted logic, and there's no need to specify $_ as it is the default. You should write if ( /perl/ )

  • You can't use say unless you have use feature 'say' at the top of your program (or use 5.010, which adds all features available in Perl v5.10)

It is also best to avoid using shell commands as Perl is more than able to do anything that you can using command line utilities. In this case -f $file is a test that returns true if the file is a plain file, and -M $file returns the (floating point) number of days since the file's modification time

This is how I would write your program

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

for my $file ( glob '/home/ad/*' ) {

    next unless -f $file and int(-M $file) == 1;

    open my $fh, '<', $file or die $!;

    while ( <$fh> ) {

        if ( /perl/ ) {

            print "found\n";

            my $filename = 'report.txt';
            open my $out_fh, '>>', $filename or die "Could not open file '$filename': $!";
            say $fh "My first report generated by perl";
            close $out_fh;

            last;
        }
    }

}

Upvotes: 1

rurouni88
rurouni88

Reputation: 1173

Change

unless ($_ =~ /perl/) {

to:

unless ($_ =~ /(Status Code 1)/) {

I am certain the above works, except it's case sensitive. Since you question it, I rewrote your script to make more sense of what you're trying to accomplish and implement the above suggestion. Correct me if I am wrong, but you're trying to make a script which matches "Status Code 1" in a bunch of files where last modified within 1 day and print the filename to a text file. Anyways, below is what I recommend:

#!/usr/bin/perl

use strict;
use warnings;

my $output_file = 'report.txt';
my @list = `find /home/ad -type f -mtime -1`;

foreach my $filename (@list) {
        print "PROCESSING: $filename";
        open (INCOMING, "<$filename") || die "FATAL: Could not open '$filename' $!";
        foreach my $line (<INCOMING>) {

                if ($line =~ /(Status Code 1)/) {
                        open( FILE, ">>$output_file") or die "FATAL: Could not open '$output_file' $!";
                        print FILE sprintf ("%s\n", $filename);
                        close(FILE) || die "FATAL: Could not CLOSE '$output_file' $!";

                        # Bail when we get the first match
                        last;
                }
        }
        close(INCOMING) || die "FATAL: Could not close '$filename' $!";
}

Upvotes: 0

karsas
karsas

Reputation: 1351

it should have matched unless $_ contains text in different case.

try this.

unless($_ =~ /Status\s+Code\s+1/i) {

Upvotes: 0

Related Questions