2010-10-03 17 views
7

Perl'de grep Unix'i nasıl uygularım? Perl'in dahili grep'u kullanmayı denedim.Perl'de Unix grep'i nasıl uygularım?

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

open($fp,$file); 

@arr = <$fp>; 

@lines = grep $pattern, @arr; 

close($fp); 
print @lines; 

Ve bu arada, ben sadece temel grep işlevselliği tam değil özellikli çalışıyorum ve ikinci olarak kendimi ayrıştırma dize yapmak istemiyorum: Burada çalışmıyor koddur. Dahili grep veya Perl'in bazı işlevlerini kullanmak istiyorum. Perl

cevap

13

:) önceden

teşekkür ederiz @ kullanmak bütün bir diziyi ifade etmek için. Ama skaler olan bireysel elemanlara başvurmak için $ kullanıyoruz.

Yani, bu hatlarda $ değil @ kullanmak gerekir: Bu

@lines = grep $pattern, @arr; 

olmalıdır Ayrıca

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

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

Perl grep genel sözdizimi var

grep EXPR,LIST 

Bu LIST her bir öğesi için EXPR değerlendirir ve ifade doğru değerlendirildiği için bu elemanların oluşturduğu liste değerini verir. Sizin durumunuzda EXPR, dizisindeki $pattern modelini arıyor.

/ olmadan /PATTERN/'u kullanmanız gerektiğine karar vermek için $pattern dizesi doğru veya yanlış olarak değerlendirilecektir.

+0

- Teşekkürler. – TCM

+2

@coddadict, koddaki hataları düzeltmeyi çok iyi yaptınız, ancak bu soru ve kullanıcı tarafından kullanılan yaklaşım onu ​​bir 'xy probleminde' dönüştürüyor, bu yüzden bu muhtemelen bir indoctrination olan konu dışı değil. Tüm dosyayı aynı anda okumamayı tavsiye etmeliydim (çizgiye yönelik grep'i simüle etmek istedi), iyi bir alışkanlık yaratmak için sadece grep() yerine grep() kullanarak onu tavsiye ederim. argümanlar açık. Ve hatta ona çevrimiçi yaklaşımı (ya da alternatif olarak çizgiyi sırayla) gösteren bir artı olurdu. –

4

Temel "grep" işlevi zaten uygulanmaktadır. (= ~) Tabii

$string =~ /pattern/; 
+0

@ user131527: - Teşekkürler! – TCM

13

, codaddict cevabı haklı, ama bazı açıklamalar eklemek istiyorum:

use strict; 
use warnings; 
: Her zaman bu iki çizgi ile komut başlamalıdır

Kullanım üç bağımsız değişken açık ve hatalar için testi:

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

ve use strict size zorunda çünkü tüm değişkenleri bildir. Dosyanız büyük

#!/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; 

varsa, bellekte tamamen okumak önleyebilirsiniz:

#!/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; 
+2

“loop @ line $ line” ile “push @lines, $ line” komutunu değiştirebilir ve herhangi bir diziden kaçınabilirsiniz. Dosyanız "büyük" ise, bir gün ya da bir şey kaçınılmaz olarak bir gün dosyanın neredeyse tüm satırlarını döndüren bir grep'i tetikler. (ve eşit büyüklükte :-) – Randall

11

doğrudan komut satırında grep ilkel bir versiyonunu yaklaşık olarak belirleyebilir gibi Yani senaryo olacak. -e seçeneği, komut satırında bir Perl betiği tanımlamanıza olanak tanır.-n seçeneği, komut dosyanızı kabaca şu şekilde sarar: while (<>){ SCRIPT }.

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

grep bir biraz daha iyi yaklaşım her baskılı maçın önüne dosya adı öneki olur. Yukarıdaki örnekte olduğu gibi bu örnekte herhangi bir dosyayı açma zahmetinden geçmediğine dikkat edin. Bunun yerine, tüm dosyalarda yineleme yapmak için Perl'in <> yapısını kullanırız ve $ARGV değişkeni geçerli dosya adını sağlar. Zaten bir cevap kabul gibi

use strict; 
use warnings; 

my $pattern = shift; 

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

'$. 'özel değişkeni geçerli satır numarasını içerir. Yani eğer bunu da yazdırmak isterseniz, 'perl -ne 'print' $ ARGV, $.: $ _"/PATTERN/'file1 file2'. – hfs

13

, ben benzer sorunlar ararken gelecek okuyucular için başvurmak üzere bu cevabı yazarken, ama değilim tam olarak senin:

kişi zaten cevap gibi

ile grep simüle yolu Perl, çevrimiçi yaklaşımı kullanmaktır. Perl'in “better” grep olarak kullanılması için (ve bul ve kes ve ...) minimal perl kitabını tavsiye ediyorum ve 'perl as a "better" grep' bölümünün örnek bölümlerden biri olduğu için şanslısınız. Son örnekte

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 akım dt ve olduğu gibi -l Dosyayı yazdırabilirsiniz maçı ile dosya bulma ilgilenen: İşte

Eğer kitaptan esinlenerek fazla örnek var Bir dosyada ilk eşleşmeden sonra bir sonraki dosya için ad ve git. Ayrıca

yerine çizgi ile paragrafta göre arama yapabilirsiniz:

$ 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. 

Veya sadece ilk eşleşme bulmak:

$ 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. 

Ve grep ve Perl hakkında sorarsanız nihayet, ben gerektiğini thay düşünüyorum ACK. Bu, grep işlevselliğini perl olarak uygular ve genişletir. Bu harika bir araçtır ve ayrıca bir CPAN paketi olarak da alabilirsiniz. Her zaman bir komut satırı olarak kullanıyorum, yöntemlerine doğrudan perl programlarınızdan erişip erişemeyeceğinizi bilmiyorum ama bu çok güzel olurdu.