From b6e4ec7b22952023405b859dea438dd55210e30f Mon Sep 17 00:00:00 2001 From: Michael Mikonos <127171689+mknos@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:59:41 +0800 Subject: [PATCH] grep: allow repeated -e and -f (#757) * If -e and -f are not provided, the first argument to grep is a pattern * If -e or -f is provided, the first argument to grep is a file * Allow multiple -e and -f options to translate to multiple elements in the patterns-list * This patch follows how GNU and BSD versions behave * Bump version * test1: "perl grep -e include -e return a.c" --> 2 patterns, one file argument * test2: "echo include > P1 && echo return > P2 && perl grep -f P1 -f P2 a.c" --> 2 pattern files with one pattern each; one file argument * test3: "grep return a.c" --> one (default) pattern argument,one file argument --- bin/grep | 63 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/bin/grep b/bin/grep index 788f87b3..569a2fad 100755 --- a/bin/grep +++ b/bin/grep @@ -54,7 +54,7 @@ use File::Spec; use File::Temp qw(); use Getopt::Std; -our $VERSION = '1.006'; +our $VERSION = '1.007'; $| = 1; # autoflush output @@ -216,39 +216,52 @@ sub parse_args { unshift @ARGV, $_; } + # multiple -e/-f options + my @tmparg; + while (@ARGV) { + my $arg = shift @ARGV; + if ($arg eq '-e') { + $pattern = shift @ARGV; + usage() unless defined $pattern; + push @patterns, $pattern; + } + elsif ($arg eq '-f') { + my $file = shift @ARGV; + usage() unless defined $file; + die "$Me: $file: is a directory\n" if -d $file; + my $fh; + open($fh, '<', $file) or die "$Me: Can't open '$file': $!\n"; + my $line; + while (defined($line = <$fh>)) { + chomp $line; + $pattern = $line; + push @patterns, $pattern; + } + close $fh; + + } + else { + push @tmparg, $arg; + } + } + @ARGV = @tmparg; + $opt{'p'} = $opt{'P'} = ''; # argument to print() getopts('inCcwsxvHhe:f:Ll1gurpP:aqTF', \%opt) or usage(); $opt{'l'} = 0 if $opt{'L'}; my $no_re = $opt{F} || ( $Me =~ /\bfgrep\b/ ); - if (defined $opt{'f'}) { # -f patfile - my $path = $opt{'f'}; - my $patfile; - die "$Me: $path: is a directory\n" if -d $path; - open($patfile, '<', $path) or die "$Me: Can't open '$path': $!\n"; - - # make sure each pattern in file is valid - while ( defined( $pattern = <$patfile> ) ) { - chomp $pattern; - unless ($no_re) { - eval { 'foo' =~ /$pattern/, 1 } - or die "$Me: $path: $.: bad pattern: $@\n"; - } - push @patterns, $pattern; - } - close $patfile; - } - else { # make sure pattern is valid - $pattern = $opt{'e'}; - $pattern = shift(@ARGV) unless length $pattern; - usage() unless defined $pattern; - unless ($no_re) { + unless (length $pattern) { + $pattern = shift @ARGV; + push @patterns, $pattern; + } + unless ($no_re) { + foreach $pattern (@patterns) { eval { 'foo' =~ /$pattern/, 1 } or die "$Me: bad pattern: $@\n"; - } - @patterns = ($pattern); } + } if ($opt{'H'}) { $Mult = 1; }