Question

I already know the obvious answer to this question: "just download <insert favorite windows grep or grep-like tool here>". However, I work in an environment with strict controls by the local IT staff as to what we're allowed to have on our computers. Suffice it to say: I have access to Perl on Windows XP. Here's a quick Perl script I came up with that does what I want, but I haven't figured up how to set up a batch file such that I can either pipe a command output into it, or pass a file (or list of files?) as an argument after the "expression to grep":

perl -n -e "print $_ if (m![expression]!);" [filename]

How do I write a batch script that I can do something like, for example:

dir | grep.bat mypattern
grep.bat mypattern myfile.txt

EDIT: Even though I marked another "answer", I wanted to give kudos to Ray Hayes answer, as it is really the "Windows Way" to do it, even if another answer is technically closer to what I wanted.

Was it helpful?

Solution

I wrote this a while back:

@rem = '--*-Perl-*--
@echo off
perl -x -S %0 %*
goto endofperl


@rem -- BEGIN PERL -- ';
#!d:/Perl/bin/perl.exe -w
#line 10
use strict; 
#use Test::Setup;
use Getopt::Long;

Getopt::Long::Configure ("bundling");

my $ignore_case    = 0;
my $number_line    = 0;
my $invert_results = 0;
my $verbose        = 0;

my $result = GetOptions( 
    'i|ignore_case' => \$ignore_case, 
    'n|number'      => \$number_line,
    'v|invert'      => \$invert_results,
    'verbose'       => \$verbose,
);
my $regex = shift;

if ( $ignore_case ) { 
    $regex = "(?i:$regex)";
}
$regex = qr/$regex/;
print "\$regex=$regex\n";
if ( $verbose ) { 
    print "Verbose: Ignoring case.\n"                      if $ignore_case;
    print "Verbose: Printing file name and line number.\n" if $number_line;
    print "Verbose: Inverting result set.\n"               if $invert_results;
    print "\n";
}

@ARGV = map { glob "$_" } @ARGV;

while ( <> ) { 
    my $matches = m/$regex/;
    next unless $matches ^ $invert_results;
    print "$ARGV\:$.:" if $number_line;
    print;
}

__END__
:endofperl

OTHER TIPS

Most of the power of grep is already available on your machine in the Windows application FindStr.exe which is part of all Windows 2000, XP and Vista machines! It offers RegExpr etc.

Far easier than a batch file which in turn calls Perl!

c:\>FindStr /?    
Searches for strings in files.

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P] [/F:file]
        [/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]]
        strings [[drive:][path]filename[ ...]]

  /B         Matches pattern if at the beginning of a line.
  /E         Matches pattern if at the end of a line.
  /L         Uses search strings literally.
  /R         Uses search strings as regular expressions.
  /S         Searches for matching files in the current directory and all
             subdirectories.
  /I         Specifies that the search is not to be case-sensitive.
  /X         Prints lines that match exactly.
  /V         Prints only lines that do not contain a match.
  /N         Prints the line number before each line that matches.
  /M         Prints only the filename if a file contains a match.
  /O         Prints character offset before each matching line.
  /P         Skip files with non-printable characters.
  /OFF[LINE] Do not skip files with offline attribute set.
  /A:attr    Specifies color attribute with two hex digits. See "color /?"
  /F:file    Reads file list from the specified file(/ stands for console).
  /C:string  Uses specified string as a literal search string.
  /G:file    Gets search strings from the specified file(/ stands for console).
  /D:dir     Search a semicolon delimited list of directories
  strings    Text to be searched for.
  [drive:][path]filename
             Specifies a file or files to search.

Use spaces to separate multiple search strings unless the argument is prefixed
with /C.  For example, 'FINDSTR "hello there" x.y' searches for "hello" or
"there" in file x.y.  'FINDSTR /C:"hello there" x.y' searches for
"hello there" in file x.y.

Regular expression quick reference:
  .        Wildcard: any character
  *        Repeat: zero or more occurances of previous character or class
  ^        Line position: beginning of line
  $        Line position: end of line
  [class]  Character class: any one character in set
  [^class] Inverse class: any one character not in set
  [x-y]    Range: any characters within the specified range
  \x       Escape: literal use of metacharacter x
  \<xyz    Word position: beginning of word
  xyz\>    Word position: end of word

Download and install ack. It's a superior replacement to grep and - thanks to Perl's magic dual mode .BAT / Perl script magic - it'll work on the command line for you.

First, turn it into a real script instead of a one-liner:

use strict;
use warnings;

my $pattern = shift or die "Usage: $0 <pattern> [files|-]\n";
while (<>) { print if /$pattern/ }

Then turn it into a batch file using pl2bat:

pl2bat mygrep.pl

This will create "mygrep.bat".

For a full-featured grep (and many other Unix applications) written completely in Perl, see the Perl Power Tools project.

While the Perl Power Tools are good if you can only run Perl, I generally prefer the set of GnuWin32 tools. They don't require installation. (You don't need administrative privileges, just a directory you can write to.)

I agree with Axeman and Mr. Hayes about using a better tool for the job. That said, you could try something like this in your batch file to run your custom script against a file wildcard expression:

@echo off

for /f "usebackq delims==" %%f in (`dir /w /b %2`) do (
    perl -n -e "print $_ if (m!%1!);" "%%f"
    REM or something like:  myperlscript.pl %1 "%%f"
)

In this way, you can do things like "grep mypattern myfile.txt", "grep mypattern .", "grep mypattern *.doc", etc.

You need to do something like this:

@echo off
perl -x -S script.pl %1

The "%1" will pass the argument to the Perl script. Save it as a .bat file, and you're good to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top