Reputation: 13
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
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
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
Reputation: 1351
it should have matched unless $_ contains text in different case.
try this.
unless($_ =~ /Status\s+Code\s+1/i) {
Upvotes: 0