Reputation: 197
I have a program that currently takes either 2 or 3 command line arguments find.pl [i] <perlRegexPattern> <listOfFiles>.
Now the program will get through my if statements if I pass find.pl proj1 Data
or find.pl -i proj1 Data
, however I want to change it so that my program will accept something like find.pl -i ".*proj1.*" DataA/*
, when I try to pass it my program doesn't make it past the 2nd if statement. I don't quite understand how to pass these as parameters and then use them in my program.
#!/usr/bin/perl -w
if(@ARGV < 2){
print "\n2) Usage: find.pl [-i] <perlRegexPattern> <listOfFiles>\n\n";
exit;
}
if(@ARGV > 3){
print "\n3) Usage: find.pl [i] <perlRegexPattern> <listOfFiles>\n\n";
exit;
}
if(@ARGV == 3 && $ARGV[0] ne "-i"){
die "\n4) Usage: find.pl [i] <perlRegexPattern> <listOfFiles>\n\n";
}
if ($#ARGV eq 1 ){
print "normal case\n";
my ($pattern, $filelist) = @ARGV;
print "$pattern $filelist\n";
opendir( DIR , $filelist ) or die "\nCannot open directory $filelist\n\n";
while ( ($fp = readdir(DIR)) ){
if( $fp =~ m/$pattern/){
print "$fp\n";
}
elsif( $fp =~ m/.*\.txt/){
print "$fp is a text file\n"; #Still working on this part
open( FILE, '<' , $fp) or die ("\nCould not open file $fp\n\n");
while( <FILE> ){
if($_ =~ m/$pattern/){
print "$fp : $_ : line pattern match\n";
last;
}
}
close(FILE);
}
}
}
else{
print "-i case\n";
my ($pattern, $filelist) = @ARGV[1 .. 2];
print "$pattern $filelist\n";
#TODO
}
Upvotes: 0
Views: 470
Reputation: 525
Take a look at the standard modules Getopt::Std
and File::Find
and note that you can save some open/close
statements by using a local
ized @ARGV
:
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
use File::Find;
## Parse option(s)
getopts 'i', \my %opt;
## Show help
die <<usage unless @ARGV > 1;
Usage:
$0 [options] pattern searchpaths...
Options:
-i Case insensitive search
usage
## Compile regex
my $re = shift;
if ($opt{i}) { $re = qr($re)i }
else { $re = qr($re) }
## Walk searchpaths
find (sub
{
## Filename matches the regex
if (/$re/)
{
printf "match name: %s\n", $File::Find::name
}
## File is regular, name ends with .txt, and...
elsif (-f and /\.txt$/)
{
local @ARGV = $_;
while (<>)
{
## ... a line in the file matches the regex.
chomp;
/$re/
and printf "match content: %s: %s\n", $File::Find::name, $_
and last;
}
}
},
@ARGV);
Example:
find.pl -i ^fa /usr/share/doc/lighttpd
Output:
match name: /usr/share/doc/lighttpd/fastcgi-state.txt
match name: /usr/share/doc/lighttpd/fastcgi.txt
match content: /usr/share/doc/lighttpd/security.txt: FastCGI
match content: /usr/share/doc/lighttpd/accesslog.txt: fastcgi + chroot
match content: /usr/share/doc/lighttpd/performance.txt: failed'. This is very rare and might only occur in test setups.
Upvotes: 1
Reputation: 53478
Your problem here is - the shell expands the wildcards before your perl script gets to them.
Try adding:
use Data::Dumper;
print Dumper \@ARGV;
And you'll see what's getting passed into your program.
Given you're using wildcards, it's likely it'll match more than one thing - and if it does, then your program will be receiving additional arguments. Only your program will only accept 3.
Upvotes: 1