2008-09-19 11 views
9

Ya sé la respuesta obvia a esta pregunta: "simplemente descargue < inserte Windows favorito grep o grep-como herramienta aquí >". Sin embargo, trabajo en un entorno con controles estrictos por parte del personal de TI local en cuanto a lo que se nos permite tener en nuestras computadoras. Baste decir: tengo acceso a Perl en Windows XP. Aquí hay un script rápido de Perl que se inventó que hace lo que yo quiero, pero no he descubierto cómo configurar un archivo por lotes de modo que pueda canalizar un resultado de comando en él o pasar un archivo (o una lista de archivos) ?) como argumento después de la "expresión de grep":¿Cómo puedo hacer que un archivo por lotes actúe como un simple grep usando Perl?

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

¿Cómo escribo un script por lotes que puedo hacer algo como, por ejemplo:

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

EDITAR: aunque Marqué otra "respuesta", quería dar kudos a Ray Hayes answer, ya que es realmente la "Manera de Windows" para hacerlo, incluso si otra respuesta es técnicamente más cerca de lo que quería.

+0

¿Desea la sintaxis grep re o la sintaxis perl más poderosa? – Axeman

Respuesta

5

de escribir este hace un tiempo:

@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 
+0

Esta fue la primera respuesta de "respuesta exacta", y parece justo lo que estaba pidiendo. Pero, como se mencionó, el "Windows Way" está usando FINDSTR. Sin embargo, definitivamente voy a mantener este pequeño guión en mi repertorio de Windows Perl, y estoy seguro de que esto, o alguna variación de él, será útil a veces. –

+0

En realidad, tenía una herramienta grep en mi PC, pero quería el poder de las expresiones de Perl para buscar. FindStr es probablemente tan bueno como grep, pero este tampoco busca archivos. Ack, como Dave Webb mencionó, hace ambas cosas. – Axeman

25

La mayor parte de la potencia de grep ya está disponible en su máquina en la aplicación de Windows FindStr.exe que es parte de todas las máquinas con Windows 2000, XP y Vista. Ofrece RegExpr, etc.

Mucho más fácil que un archivo por lotes que a su vez llama a 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 
+0

¡Esto es asombroso! Y un gran consejo para un geek de Unix que intenta "hacerlo" en la plataforma de Windows. Incluso si no respondiera directamente mi pregunta :-) –

1

que tiene que hacer algo como esto:

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

El "% 1" pasará el argumento al script Perl. Guárdelo como un archivo .bat, y listo.

+0

¿Funcionaría eso con una tubería? Quiero decir, si uso tu archivo bat como este 'gcc -MM archivos | yourbat regexp'. Intenté esto con 'ack' y obtuve un comportamiento inesperado. – Gauthier

1

Estoy de acuerdo con Hacha y el Sr. Hayes sobre el uso de una mejor herramienta para el trabajo. Dicho esto, podría intentar algo como esto en su archivo por lotes para ejecutar el script personalizado con una expresión comodín archivo:

@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" 
) 

De esta manera, se pueden hacer cosas como "grep miarchivo.txt myPattern", "grep mypattern. "," grep mypattern * .doc ", etc.

+0

Este es un tidbit útil. A través de una pequeña cantidad de búsqueda, he encontrado muy poco en la web sobre el uso de argumentos, tuberías, etc. en archivos por lotes. Esto definitivamente enciende una bombilla de luz para mí, ¡gracias! –

11

Descargue e instale ack. Es un reemplazo superior para grep y, gracias al mágico modo de perl Magia de secuencia de comandos .BAT/Perl, funcionará en la línea de comandos para ti.

+0

Bueno, especifiqué específicamente que tengo un entorno estricto en mi PC de lo que puedo instalar. Sin embargo, esta puede ser una buena opción, ya que parece ser una descarga de solo fuente y mi departamento de TI probablemente la deje pasar. Buena sugerencia. –

+0

Sí, también iba a sugerir sugerencias, pero sé que algunos departamentos de TI son estrictos con respecto a los complementos de Firefox y módulos Perl no autorizados. Entonces, si puede escribir sus propios archivos por lotes, puede hacerlo. pero parece que FindStr es un salto por encima del DOS. – Axeman

5

En primer lugar, convertirlo en un guión real en lugar de una sola línea:

use strict; 
use warnings; 

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

A continuación, convertirlo en un archivo por lotes utilizando pl2bat:

pl2bat mygrep.pl 

Esto creará "mygrep.bat ".

Para un grep con todas las funciones (y muchas otras aplicaciones de Unix) escritas completamente en Perl, vea el proyecto Perl Power Tools.

Si bien las Perl Power Tools son buenas si solo puedes ejecutar Perl, generalmente prefiero el conjunto de herramientas GnuWin32.No requieren instalación. (No necesita privilegios administrativos, solo un directorio en el que puede escribir)

Cuestiones relacionadas