Reputation: 1851
My question is probably simple but I'm a complete newbie. I want to search the contents of multiple text files for a particular phrase and then display the lines of the finds on screen. I've already learnt how to deal with a single file. For example, if I want to search for a word, say "Okay" in a text file named "wyvern.txt" in the root directory of F. The following code works:
#!/usr/bin/perl
$file = 'F:\wyvern.txt';
open(txt, $file);
while($line = <txt>) {
print "$line" if $line =~ /Okay/;
}
close(txt);
But what should I do if I want to search for the same phrase in two text files, say "wyvern' and "casanova" respectively? or how about all the files in the directory "novels" in the root directory of F.
Any help would be greatly appreciated. Thanks in advance
Mike
Edit:
Haha, I finally figured out how to search all the files in a directory for a pattern match:) The following code works great:
#!/usr/bin/perl
@files = <F:/novels/*>;
foreach $file (@files) {
open (FILE, "$file");
while($line= <FILE> ){
print "$line" if $line =~ /Okay/;
}
close FILE;
}
Upvotes: 11
Views: 33591
Reputation: 1304
Just a tweak on your line: <F:/novels/*>
, I prefer to use the glob
keyword - it works the same in this context and avoids the chances of confusing the many different uses of angle brackets in perl. Ie:
@files = glob "F:/novels/*";
See perldoc glob for more.
Upvotes: 2
Reputation: 118118
On a system where command line arguments are properly expanded, you can use:
[sinan@host:~/test]$ perl -ne 'print "$.:$_" if /config/' * 1:$(srcdir)/config/override.m4
The problem with Windows is:
C:\Temp> perl -ne "print if /perl/" *.txt Can't open *.txt: Invalid argument.
On Windows, you could do:
C:\Temp> for %f in (*.txt) do perl -ne "print if /perl/" %f
But, you might just want to use cmd.exe
builtin findstr or the grep command line tool.
Upvotes: 4
Reputation: 1851
Okay, I'm a complete dummie. But to sum up, I now can search one single text file or multiple text files for a specified string. I'm still trying to figuring out how to deal with all the files in one folder. the following codes work.
#!/usr/bin/perl
$file = 'F:\one.txt';
open(txt, $file);
while($line = <txt>) {
print "$line" if $line =~ /Okay/;
}
close(txt);
#!/usr/bin/perl
{
local @ARGV = ('F:\wyvern.txt', 'F:\casanova.txt');
while (<>) {
print "$ARGV:$.:$_" if /Okay/;
} continue {
close ARGV if eof;
}
}
Thanks again for your help. I really appreciate it.
Upvotes: 0
Reputation: 239652
Extending the good answer provided by Jonathan Leffler:
The filename where the match was found is in $ARGV
, and with a small change, the line number can be found in $.
. Example:
while (<>) {
print "$ARGV:$.:$_" if /pattern/;
} continue {
close ARGV if eof; # Reset $. at the end of each file.
}
Furthermore, if you have a list of filenames and they're not on the commandline, you can still get the magic ARGV
behavior. Watch:
{
local @ARGV = ('one.txt', 'two.txt');
while (<>) {
print "$ARGV:$.:$_" if /Okay/;
} continue {
close ARGV if eof;
}
}
Which is a generally useful pattern for doing line-by-line processing on a series of files, whatever it is -- even if I might recommend File::Grep
or App::Ack
for this specific problem :)
Upvotes: 8
Reputation: 449
put the files in a for loop, or something along those lines:
i.e.
for $file ('F:\wyvern.txt','F:\casanova.txt') {
open(TXT, $file);
while($line = <txt>) {
print "$line" if $line =~ /Okay/;
}
close TXT;
}
Upvotes: 1
Reputation: 753455
The easiest way is to list the files on the command line, and then simply use:
while (<>)
{
print if m/Okay/;
}
Upvotes: 3