Command-Line Options
#!/usr/bin/perl -w
use Getopt::Std;
# Duplicate grep with -l, -v, and -n the allowable options. Die if
# an option is given which does not exist! Getopts provides error
# message which is sent to STDERR. Options can be after one hyphen
# (e.g. -vn) or separately (e.g. -v -n).
die "\n" if !getopts("lvn", \%opts);
# The options now will NOT be considered part of the @ARGV array.
die "Usage: $0 [-lvn] \"pattern\" file1 ...\n" if @ARGV < 2;
die "Incompatible options!\n" if $opts{'l'} && $opts{'n'};
$pattern = shift @ARGV; # Get pattern for our own grep.
foreach $file (@ARGV)
{
if (!open(F, "$file"))
{
print "Could not open $file!\n";
next;
}
if (!-T "$file")
{
print "Skipping $file -- not a text file!\n";
next;
}
if ($opts{'l'})
{
@matches = grep {/$pattern/} <F> if !$opts{'v'};
@matches = grep {!/$pattern/} <F> if $opts{'v'};
print "$file\n" if @matches;
}
elsif ($opts{'n'})
{
$matches = 0;
while (<F>)
{
if ($opts{'v'} ? !/$pattern/ : /$pattern/)
{
$matches++;
print "$file\n", "-" x length($file), "\n" if $matches == 1;
printf "%-10s: %-s", $., $_ ;
}
}
}
else # No options at all or just $opt_v.
{
@matches = grep {!/$pattern/} <F> if $opts{'v'};
@matches = grep {/$pattern/} <F> if !$opts{'v'};
next if !@matches;
print "$file\n", "-" x length($file), "\n";
print join("", @matches), "\n";
}
close F; # Reset $. -- not done without explicit close.
}
########################## Sample Sessions with Script #####################
$ mygrep.pl getopts getopts.pl database.demo.8 # "Getopts" is pattern.
getopts.pl
----------
getopts("lvn", \%opts);
$ mygrep.pl foobar * # "Foobar" is pattern.
Skipping emp.db -- not a text file!
Skipping events.db -- not a text file!
grep-map.demo.2
---------------
@strs = qw(foobar simple four on eighteen);
Skipping homers.db -- not a text file!
Skipping objects -- not a text file!
signals.demo.11
---------------
foobar
Output: foobar
foobar
Output: foobar
sort.demo.5
-----------
@list = qw(goofy foobar xxxxxx john perl);
Sum for foobar: 633
foobar
$ mygrep.pl -n foobar *
Skipping emp.db -- not a text file!
Skipping events.db -- not a text file!
grep-map.demo.2
---------------
29 : @strs = qw(foobar simple four on eighteen);
Skipping homers.db -- not a text file!
Skipping objects -- not a text file!
signals.demo.11
---------------
135 : foobar
136 : Output: foobar
158 : foobar
159 : Output: foobar
sort.demo.5
-----------
78 : @list = qw(goofy foobar xxxxxx john perl);
180 : Sum for foobar: 633
188 : foobar
$ mygrep.pl -vln foobar *
Incompatible options!
$ mygrep.pl -c mygrep mygrep.pl
Unknown option: c
################## Command Line Options with Arguments ##################
#!/usr/bin/perl -w
use Getopt::Std;
# Duplicate head and tail in one utility. Option -s means "start at line"
# and then the line number. Option -h means "head". Option -t means
# "tail". Unfortunately, there are no defaults if you specify a : in
# the option string. Here the options mutually exclusive.
die "\n" if !getopts("s:h:t:", \%opts);
die "Usage: $0 [-s arg -h arg -t arg] file\n" if @ARGV != 1;
open(F, "$ARGV[0]") or die "Cannot open $ARGV[0]!\n";
# Bail if more than one argument present or if none are present.
# If no hash reference is given to the getopts function, then the
# option arguments are held in $opts{t}, $opts{h}, and $opts{s} in this
# program. If you do give a hash reference, USE THE HASH!!
@numopts = keys %opts;
die "May only use one option!\n" if @numopts > 1;
die "Must use one option!\n" if @numopts == 0;
$line = $opts{$numopts[0]}; # Only one option, must be in [0] index!
die "Illegal option argument!\n" if $line =~ /\D/ || $line == 0;
# See how many lines we have for -t option. Then rewind file, reset $.
@lines = <F>;
die "Illegal linenumber!\n" if $line > @lines;
seek(F, 0, 0);
$. = 0; # Necessary!!
while (<F>)
{
if ($opts{s}) # If $opts{s} is set it will have a linenumber in it.
{
printf "%-5d: %-s", $., $_ if $. >= $line;
}
if ($opts{h})
{
printf "%-5d: %-s", $., $_ if $. <= $line;
last if $. > $line; # Why do more work than we need to?
}
if ($opts{t})
{
printf "%-5d: %-s", $., $_ if $. > @lines - $line;
}
}
########################## Program Sessions Below #########################
$ display.pl getopts2.pl
Must use one option!
$ display.pl -h 10 -s 10 getopts2.pl
May only use one option!
$ display.pl -s getopts2.pl # Proof that option MUST have an argument!
Usage: ./display.pl [-s arg -h arg -t arg] file
$ display.pl -h3 getopts2.pl # Note that arg can run into option string!
1 : #!/usr/bin/perl -w
2 :
3 : use Getopt::Std;
$ display.pl -t 4 getopts2.pl
42 : {
43 : printf "%-5d: %-s", $., $_ if $. > @lines - $line;
44 : }
45 : }
$ display.pl -s 40 getopts2.pl
40 : }
41 : if ($opt_t)
42 : {
43 : printf "%-5d: %-s", $., $_ if $. > @lines - $line;
44 : }
45 : }
$
# Notes on using options with and without arguments:
# 1) If your getopts line says that an option has an argument,
# the argument MUST be there. No defaults!!
#
# 2) If an option has an argument, then its value will be in the
# hash given to getopts. Example, if you have a -X option
# which takes an argument and your options hash is %opts,
# then $opts{'X'} will contain the argument value if -X is
# on the user's command line.
#
# 3) If an option, say the -X above, does NOT have an argument,
# then $opts{'X'} will be 1 if -X is present and 0 if not.
#
# 4) Getopts removes all options and option arguments from @ARGV!
#
# 5) When using getopts, use die "\n" because getopts itself will
# provide all necessary error messages.