[Israel.pm] little bit O.T. :Perl regex vs grep regex

Mark Dominus mjd-list-israelpm at plover.com
Thu Nov 11 18:50:06 PST 2004


> I hope this is not too mach off topic,
> is there any CLI tool that equals to the bash command line tool "grep"
> but with the power of perl regexes?

A cheap solution is

        my $pat = shift;
        while (<>) { print if /$pat/o }

But I recently wrote a fancier version, which I have been using a lot
this year.  It may not have the options you want, because I gave it
only the options that *I* want:

        #!/usr/bin/perl
        #
        # pgrep - Perl grep
        # Copyright 2004 Mark Dominus (mjd at plover.com)
        #

        use Getopt::Std;
        my $opts = 'ulhIive:F:q';
        getopts($opts) or usage();
        my $pat = defined($opt_e) ? $opt_e : @ARGV ? shift : usage();
        my $qr = $opt_i ? qr/$pat/i : qr/$pat/;

        my $format;

        if (defined $opt_F) {
          $format = $opt_F . "\n";
        } else {
          my %format = (l => '%s'."\n",
                        h => '%2$s'."\n",
                        q => "",
                        "" => $opt_I || @ARGV > 1 ? "%s: %s\n" : '%2$s'."\n",
                       );
          my $fk = "";
          $fk .= 'l' if $opt_l;
          $fk .= 'h' if $opt_h;
          $fk .= 'q' if $opt_q;
          $format = $format{$fk};
          unless (defined $format) {
            warn "Incompatible options.\n";
            usage();
          }
        }

        $| = 1 if $opt_u;

        $rc = 1;  # No matches;

        if ($opt_I) {
          while (<STDIN>) { chomp; do_file($_) }
        } elsif (@ARGV) {
          do_file($_) for @ARGV;
        } else {
          do_file(\*STDIN);
        }
        exit $rc;

        sub do_file {
          my $file = shift;
          my $fh;
          if (ref $file) {
            $fh = $file;
            $file = "<stdin>";
          } else {
            return if -d $file || -B $file;
            unless (open $fh, "<", $file) {
              warn "Couldn't open '$file': $!; skipping\n";
              return;
            }
          }

          while (<$fh>) {
            chomp;
            if (/$qr/ ^ $opt_v) {
              $rc = 0;                  # match
              printf $format, $file, $_, $.;
              return if $opt_l;
            }
          }
        }

        sub usage {
          print STDERR <<EOM;
         Usage: $0 [$opts] pattern files...

            -F format    printf-style output format 
                         (%1\$s = filename, %2\$s = text, %3\$d = line number)
            -e pattern   specify pattern
            -h           omit filenames
            -i           case-insensitive match
            -I           list of files on STDIN instead of in ARGV
            -l           print filenames only
            -q           print nothing
            -u           make output unbuffered
            -v           invert matching
        EOM
          exit 2;
        }


There's also a Tom Christiansen program called "tcgrep" you might want
to look for.  I think the code might be in "Perl Cookbook".



More information about the Perl mailing list