diff options
Diffstat (limited to 'bsgrep')
-rwxr-xr-x | bsgrep | 91 |
1 files changed, 65 insertions, 26 deletions
@@ -28,16 +28,29 @@ $SIG{__WARN__} = sub { print STDERR $m unless $opt{s}; }; -sub grep_usage { - print "usage: $self [--help | --version | -[Fhiklnrsvwqz] [-d char] ...] <regex> [<file> ...]\n"; -} - sub grep_options { - getopts('d:Fhiklnqrsvwz', \%opt) || exit 1; - if($opt{h}) { - grep_usage(); - exit(0); + my @nargv; + my $was_e; + + # first, grab all the -e options and remove them from @ARGV, + # because Getopt::Std doesn't support multiple occurrences of + # a flag with different args. probably it would be better to + # use Getopt::Long, but for now this works. + for(@ARGV) { + if($was_e) { + push @patterns, $_; + $was_e = 0; + } elsif($_ eq '-e') { + $was_e = 1; + } elsif($_ =~ /-e(.*)/) { + push @patterns, $1; + } else { + push @nargv, $_; + } } + @ARGV = @nargv; + + getopts('d:FhiklnNqrsvwz', \%opt) || exit 1; } sub print_line { @@ -58,17 +71,31 @@ sub join_options { } sub handle_line { - local $_ = $_[0]; + my $match = 0; + + for my $pat (@patterns) { + if($opt{v}) { + $match++ if $out !~ /$pat/; + } else { + $match++ if $out =~ /$pat/; + } + } + + return unless $match; + + if($opt{N}) { + return unless $match == @patterns; + } + $ret = 0 if $ret == 1; return if $opt{q}; + if($opt{l}) { if(!$printed{$ARGV}++) { print "$ARGV\n"; } - } elsif($opt{v}) { - print_line($out) if $out !~ /$regex/; } else { - print_line($out) if $out =~ /$regex/; + print_line($out); } } @@ -98,15 +125,19 @@ if(defined($ARGV[0])) { if($self =~ /join/) { join_options(); - $regex = '^'; # every string has a beginning... + push @patterns, '^'; # every string has a beginning... } else { grep_options(); - if(!($regex = shift)) { - grep_usage(); - die("$self: missing required regex argument\n"); + + if(!@patterns) { + if(!($patterns[0] = shift)) { + grep_usage(); + die("$self: missing required pattern argument\n"); + } } - $regex = quotemeta($regex) if $opt{F}; - $regex = "(?i)$regex" if $opt{i}; + + map { $_ = quotemeta } @patterns if $opt{F}; + map { $_ = "(?i)$_" } @patterns if $opt{i}; } if($opt{r}) { @@ -153,7 +184,7 @@ while(<>) { $out =~ s/$cont$//; } } else { - handle_line($out); + handle_line(); undef $out; } } continue { @@ -161,7 +192,7 @@ while(<>) { if(eof) { if($out) { warn "$self: $ARGV:$.: last line ends with continuation\n" unless $opt{s}; - handle_line($out); + handle_line(); undef $out; } close ARGV; @@ -183,7 +214,7 @@ bsjoin - join lines with backslash continuation =head1 SYNOPSIS -bsgrep [B<[-hknwz]> B<-d> I<char> I<...>] [I<file> I<...>] +bsgrep [B<[-hknwz]> B<-d> I<char> I<...>] [B<-e> I<pattern> ... | I<pattern>] [I<file> I<...>] bsjoin [B<[-hiklnqrsvwz]> B<-d> I<char> I<...>] [I<file> I<...>] @@ -235,11 +266,6 @@ For continuation lines, remove any leading whitespace. This option is specific to B<bsgrep>. The B<grep> B<-w> option can be simulated with the Perl B<\b> syntax in the regex. -=item -h - -Prints a short help message and exits. Not compatible with B<grep>, which -uses B<-h> for something else. - =item -z Use zero bytes (ASCII NUL) rather than newlines for line terminators, @@ -265,6 +291,12 @@ These options are only supported by B<bsgrep>: =over 4 +=item -e I<pattern> + +Use I<pattern> as the pattern. May be used multiple times, in which case +they are ORed together (a line that matches any I<pattern> is a match)... unless +the B<-N> option is used, q.v. Same as B<grep>. + =item -F Treat pattern(s) as fixed strings, not regular expression(s). Same as B<grep>. @@ -278,6 +310,13 @@ Case-insensitive search (same as B<grep>). Instead of printing lines that match, print only the names of files that contain matches (same as B<grep>). +=item -N + +When multiple patterns are given with multiple B<-e> options, only +select lines that match all of the patterns; the default is to select +lines that match any of the patterns. This option doesn't exist +in B<grep>. + =item -r Recursively read all files under each directory, following symlinks |