簡體   English   中英

如何在Perl中實現Unix grep?

[英]How can I implement Unix grep in Perl?

如何在Perl中實現Unix的grep 我嘗試使用Perl的內置grep 這是不起作用的代碼:

$pattern = @ARGV[0];
$file= @ARGV[1];

open($fp,$file);

@arr = <$fp>;

@lines = grep $pattern, @arr;

close($fp);
print @lines;

順便說一句,我只嘗試基本的grep功能不完整功能,其次我不想自己進行字符串解析。 我想使用內置的grep或Perl的一些功能。

提前致謝 :)

正如您已經接受了答案,我正在編寫此答案以供將來讀者搜索類似問題的參考,但不完全是您的:

正如人們已經回答的那樣,使用perl模擬grep的方法是使用在線方法。 對於使用perl作為'更好'的grep(以及查找和剪切......),我推薦本書最小的perl ,你很幸運,因為'perl as a“grep'這一章是示例章節之一。

這里有更多來自本書的例子:

perl -wnle '/foo/ and print' null.txt  # normal grep
perl -wnle '/foo/ and print "$ARGV: $_"' null.txt # grep -H
perl -wnle '/foo/ and print $ARGV and close ARGV' null_1.txt null_2.txt # grep -l

在最后一個示例中,ARGV是當前文件句柄,與-l一樣,您有興趣查找具有匹配項的文件,您可以打印文件名,並在文件中第一次匹配后轉到下一個文件。

您也可以逐行搜索:

$ perl -00 -wnl -e '/\bBRIBE\b/i and print;' SenQ.testimony
I knew I'd be in trouble if
I ACCEPTED THE BRIBE!
So I did not.

My minimum bribe is $100k, and she only offered me $50k,
so to preserve my pricing power, I refused it.

或者只找到第一場比賽:

$ perl -00 -wnl -e '/\bBRIBE\b/i and close ARGV;' SenQ.testimony
I knew I would be in trouble if
I ACCEPTED THE BRIBE!
So I did not.

最后,如果你問grep和perl,我想我應該提一下ACK 它在perl中實現了grep功能並對其進行了擴展。 這是一個很棒的工具,作為一個加分,你可以把它作為一個CPAN包。 我總是使用命令行,我不知道你是否可以直接從你的perl程序訪問它的方法,但這將是非常好的。

在Perl中引用整個數組我們使用@ 但是要引用標量的各個元素,我們使用$

所以,你需要在這些行上使用$而不是@

$pattern = @ARGV[0];
$file= @ARGV[1];

這個

@lines = grep $pattern, @arr;

應該

@lines = grep /$pattern/, @arr;

Perl中的grep具有以下一般語法:

grep EXPR,LIST

它評估LIST每個元素的EXPR ,並返回由表達式求值為true的元素組成的列表值。

您的案例中的EXPR正在搜索數組@arr的模式$pattern 要搜索,您需要使用/PATTERN/而不使用/字符串$pattern將被評估為true或false。

當然,codaddict的回答是正確的,但我想補充一些評論:

您應該始終使用以下兩行開始腳本:

use strict;
use warnings;

使用三個args打開並測試錯誤:

open my $fh, '<', $file or die "unable to open '$file' for reading : $!";

而且由於use strict你必須聲明所有變量。 所以你的腳本將是這樣的:

#!/usr/bin/perl

use strict;
use warnings;

my $pattern = $ARGV[0];
my $file = $ARGV[1];

open $fh, '<', $file or die "unable to open file '$file' for reading : $!";
my @arr = <$fh>;
close $fh;  # close as soon as possible

my @lines = grep /$pattern/, @arr;

print @lines;

如果您的文件很大,您可以避免在內存中完全讀取它:

#!/usr/bin/perl
use strict;
use warnings;

my $pattern = qr/$ARGV[0]/;
my $file= $ARGV[1];
print "pattern=$pattern\n";

my @lines;
open my $fh, '<', $file or die "unable to open file '$file' for reading : $!";
while(my $line=<$fh>) {
    push @lines, $line if ($line =~ $pattern);
}
close($fh);
print @lines;

您可以直接在命令行上逼近grep的原始版本。 -e選項允許您在命令行上定義Perl腳本。 -n選項大致包裝你的腳本: while (<>){ SCRIPT }

perl -ne 'print if /PATTERN/' FILE1 FILE2 ...

稍微好一點的grep將在每個打印的匹配前面添加文件名前綴。 請注意,此示例與上面的示例一樣,不會經歷打開任何文件的麻煩。 相反,我們使用Perl的<>構造來遍歷所有文件, $ARGV變量提供當前文件名。

use strict;
use warnings;

my $pattern = shift;

while (my $line = <>){
    print $ARGV, ':', $line if $line =~ $pattern;
}

基本的“grep”功能已經實現。 (=〜)

$string =~ /pattern/;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM