Come posso fare in modo che un file batch si comporti come un semplice grep usando Perl?
-
01-07-2019 - |
Domanda
Conosco già la risposta ovvia a questa domanda: " basta scaricare < inserire qui lo strumento windows grep o grep preferito > " ;. Tuttavia, lavoro in un ambiente con severi controlli da parte del personale IT locale su ciò che ci è permesso avere sui nostri computer. Basti dire: ho accesso a Perl su Windows XP. Ecco un veloce script Perl che ho ideato che fa quello che voglio, ma non ho capito come impostare un file batch in modo da poter reindirizzare un comando in uscita o passare un file (o un elenco di file ?) come argomento dopo l'espressione " in grep " ;:
perl -n -e "print $_ if (m![expression]!);" [filename]
Come posso scrivere uno script batch che posso fare qualcosa del genere, ad esempio:
dir | grep.bat mypattern grep.bat mypattern myfile.txt
EDIT : anche se ho segnato un altro " answer " ;, volevo dare i miei complimenti a Ray Hayes risponde , dato che è davvero il & Quot ; Windows Way & Quot; per farlo, anche se un'altra risposta è tecnicamente più vicina a ciò che volevo.
Soluzione
L'ho scritto qualche tempo fa:
@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
Altri suggerimenti
La maggior parte della potenza di grep è già disponibile sul tuo computer nell'applicazione FindStr.exe di Windows che fa parte di tutti i computer Windows 2000, XP e Vista! Offre RegExpr ecc.
Molto più semplice di un file batch che a sua volta chiama 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
Scarica e installa ack . È un sostituto superiore di grep e - grazie alla doppia modalità magica di Perl .BAT / script di magia magica - funzionerà sulla riga di comando per te.
Innanzitutto, trasformalo in un vero script anziché in una riga:
use strict;
use warnings;
my $pattern = shift or die "Usage: $0 <pattern> [files|-]\n";
while (<>) { print if /$pattern/ }
Quindi trasformalo in un file batch usando pl2bat:
pl2bat mygrep.pl
Questo creerà " mygrep.bat " ;.
Per un grep completo (e molte altre applicazioni Unix) scritto completamente in Perl, vedi Progetto Perl Power Tools .
Mentre gli utensili elettrici Perl sono buoni se si può eseguire solo Perl, in genere preferisco l'insieme di GnuWin32 strumenti. Non richiedono installazione. (Non hai bisogno di privilegi di amministratore, solo una directory in cui puoi scrivere.)
Sono d'accordo con Axeman e Mr. Hayes sull'utilizzo di uno strumento migliore per il lavoro. Detto questo, potresti provare qualcosa del genere nel tuo file batch per eseguire lo script personalizzato su un'espressione jolly di file:
@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 questo modo, puoi fare cose come " grep mypattern myfile.txt " ;, " grep mypattern. " ;, " grep mypattern * .doc " ;, ecc.
Devi fare qualcosa del genere:
@echo off
perl -x -S script.pl %1
Il "% 1 " passerà l'argomento allo script Perl. Salvalo come file .bat e sei a posto.