windows 如何使用 Perl 使批处理文件像简单的 grep 一样工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/106053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:15:33  来源:igfitidea点击:

How can I make a batch file to act like a simple grep using Perl?

windowsperlbatch-file

提问by Ogre Psalm33

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":

我已经知道这个问题的明显答案:“只需下载<在此处插入最喜欢的 windows grep 或类似 grep 的工具>”。但是,我在当地 IT 人员严格控制我们可以在计算机上使用的内容的环境中工作。我只想说:我可以在 Windows XP 上访问 Perl。这是我想出的一个快速 Perl 脚本,它可以满足我的要求,但我还没有想出如何设置批处理文件,以便我可以将命令输出通过管道传输到其中,或者传递一个文件(或文件列表) ?) 作为“表达式到 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.

编辑:即使我标记了另一个“答案”,我还是想赞扬Ray Hayes 的答案,因为它确实是“Windows 方式”,即使另一个答案在技术上更接近我想要的。

采纳答案by Axeman

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

回答by Ray Hayes

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.

grep 的大部分功能已经在您的计算机上的 Windows 应用程序 FindStr.exe 中可用,它是所有 Windows 2000、XP 和 Vista 计算机的一部分!它提供 RegExpr 等。

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

比批处理文件更容易,后者又调用 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

回答by hexten

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.

下载并安装ack。它是 grep 的绝佳替代品,而且 - 由于 Perl 的神奇双模式 .BAT / Perl 脚本魔法 - 它可以在命令行上为您工作。

回答by Michael Carman

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

首先,把它变成一个真正的脚本而不是一个单行:

use strict;
use warnings;

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

Then turn it into a batch file using pl2bat:

然后使用 pl2bat 将其转换为批处理文件:

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

This will create "mygrep.bat".

这将创建“mygrep.bat”。

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

有关完全用 Perl 编写的全功能 grep(以及许多其他 Unix 应用程序),请参阅Perl Power Tools项目。

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

如果您只能运行 Perl,Perl Power Tools 是不错的选择,但我通常更喜欢GnuWin32工具集。它们不需要安装。(您不需要管理权限,只需一个可以写入的目录。)

回答by Jim Olsen

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:

我同意 Axeman 和 Hayes 先生关于使用更好的工具来完成这项工作的意见。也就是说,您可以在批处理文件中尝试类似的操作,以针对文件通配符表达式运行自定义脚本:

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

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

通过这种方式,您可以执行“grep mypattern myfile.txt”、“grep mypattern .”、“grep mypattern *.doc”等操作。

回答by ian93

You need to do something like this:

你需要做这样的事情:

##代码##

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

“%1”将把参数传递给 Perl 脚本。将其另存为 .bat 文件,您就可以开始使用了。