2009-09-18 17 views
7

Aynı anda çok satırlı bir satır bir satırı işlemek için uygun PBP onaylı yolu anlamaya çalışıyorum. Birçok Perl kodlayıcısı, çok satırlı dizeyi bir "el yapımı" olarak ele almayı önerir. Sonra sıkı refs kullanımda iken bir dize bir sembol olarak kullanamamak hakkında derleyici bir uyarı alırsınız. dışarı yorum satırı "katı kullanın" diyeÇok satırlı bir dizeyi perl'de bir kerede bir kerede sıkı kullanımla nasıl işleyebilirim?

#use strict; 
use warnings; 

my $return = `dir`; 
my $ResultsHandle = ""; 
my $matchLines = ""; 
my $resultLine = ""; 
open $ResultsHandle, '<', \$return; 
while (defined ($resultLine = <$ResultsHandle>)) { 
    if ($resultLine =~ m/joe/) { 
     $matchLines = $matchLines . "\t" . $resultLine; 
    } 
} 
close($ResultsHandle); 
print "Original string: \n$return\n"; 
print "Found these matching lines: \n$matchLines\n"; 

Uyarı:

İşte sorunun basit bir çalışma örnek. Ben kullanılmadan sıkı Bu komut dosyasını çalıştırdığınızda, istediğim ve beklediğiniz olsun:

Original string: 
Volume in drive D has no label. 
Volume Serial Number is 50D3-54A6 

Directory of D:\Documents and Settings\username\My Documents\Eclipse\myTestProject 

09/18/2009 11:38 AM <DIR>   . 
09/18/2009 11:38 AM <DIR>   .. 
09/18/2009 11:36 AM    394 .project 
09/18/2009 11:37 AM     0 joe.txt 
09/18/2009 11:37 AM     0 joey.txt 
09/18/2009 11:38 AM     0 kurt.txt 
09/18/2009 11:43 AM    497 main.pl 
09/18/2009 11:38 AM     0 shane.txt 
       6 File(s)   891 bytes 
       2 Dir(s) 6,656,188,416 bytes free 

Found these matching lines: 
    09/18/2009 11:37 AM     0 joe.txt 
    09/18/2009 11:37 AM     0 joey.txt 

Burada olsa, sorun da bu. "Açık $ ResultsHandle, '<', \ $ dönüşü;" 8

Can't use string ("") as a symbol ref while "strict refs" in use at D:/Documents and Settings/username/My Documents/Eclipse/myTestProject/main.pl line 8. 

Hattı: Ben yorumsuz zaman çizgisini "sıkı kullanmak", ben Perl aşağıdaki uyarıyı veya hatayı alıyorum hat, bu arada. Perl Best Practices'ın sıkı bir şekilde kullanmamı gerektirdiğinden, PBP bir seferde çok satırlı bir satırı bir satır işlemem için nasıl bekliyor? SO topluluğundan herhangi bir öneriniz var mı?

Teşekkürler!

+4

C (üstte) ve Perl'in kendisi tarafından kolayca elde edilebilecek bir şey için backtick kullanımı. – innaM

+1

Teşekkürler, Manni. Dizin içeriği alımı sadece gösterim amaçlıydı. Gerçek programım aslında başka bir program çağırıyor ve çıkışını işler. Ve eski moda değişken başlatma, daha fazla çalışmam gereken bir şey. Ama sık sık eski komut dosyalarından kesip yapıştırırım. :-) Yine de daha iyisini yapmaya çalışıyorum. –

cevap

11

$ResultsHandle initialize etmeyin:

use strict; 
use warnings; 

my $return = `dir`; 
my $ResultsHandle; # <-- leave undefined 
my $matchLines = ""; 
my $resultLine = ""; 
open $ResultsHandle, '<', \$return; 
while (defined ($resultLine = <$ResultsHandle>)) { 
    if ($resultLine =~ m/joe/) { 
     $matchLines = $matchLines . "\t" . $resultLine; 
    } 
} 
close($ResultsHandle); 
print "Original string: \n$return\n"; 
print "Found these matching lines: \n$matchLines\n"; 

Eğerönce tanımlanmamış $ResultsHandle bırakırsanız, dosya tanıtıcısına bir başvuru ile doldurulacaktır. open() bir dizgiye ayarladığınız için, use strict altında bir değişkenin sembolik bir referansı olması gerektiği varsayılmıştır.

+0

Vay. Teşekkürler! Perl hakkında ne kadar az şey bildiğimi gösterir! Sanırım bunu SOMETHING'e başlatmam gerektiğini düşündüm. Sanırım yanılıyordum. Hızlı cevap için teşekkürler! –

+0

Ayrıca, "katı" anlamadığım da gösteriyor. Derleyiciyi ve Perl Critic modülünü, her ikisini de oluşturdukları tüm mesajları tam olarak anlamadan memnun etmeye çalışıyorum. –

+2

Bunu düşünmenin başka bir yolu: 'open()' sizin için başlatır $ ResultsHandle' sizin için *, henüz başlatılmamışsa *. '' use strict '', zaman zaman yararlı olabilecek şeyleri reddeder, ancak daha sık sık belaya neden olur. – dave4420

3

split ile tek satır dizeleri bir liste halinde çok hatlı dize dönüştürme:

my @resultLines = split /\n/, $result;  # or /\r\n/ for Windows? 
foreach my $resultLine (@resultLines) { 
    if ($resultLine =~ m/joe/) { 
     $matchLines 
      = $matchLines . "\t" 
       . $resultLine . "\n"; # put \n or \r\n back on the end 
    } 
} 
+0

, '\ n' satır ayırıcı olarak kullanırsanız, \ n karakterleri $ resultLine değişkenine atar. bölünmüş/^/m, $ sonuç daha iyi kullan, satır sonu ile tüm satırı atayacaktır. Sabırlı olun, son satırda her zaman çizgi karakterlerinin sonu olmaz. – Znik

0

Aç "dir" komutu bir boru kullanarak bir dt.

E.g.

open my $FOO, "dir|" or die "Can not run 'dir': $!"; 
+2

Gerçekten. "Dir" şartı varsa, boru için gidin. Ama readdir veya basit bir glob kullanmayı tercih ederim. – innaM

2

Değişim

my $ResultsHandle = ""; 

için
my $ResultsHandle; 
7

daha özlü PBP yolu şöyle open kullanmaktır: Bu da daha önceki ihtiyacını ortadan kaldırır

open my $ResultsHandle, '<', \$return; 

"Benim $ Resultshandle;" Beyan ettiğiniz ve içeri girdiğinizi bildiren numaralı numaralı uyarıyı engeller.

4

Ayrıca bir yineleyici olarak regexpi kullanabilirsiniz:

my $data = q{Hello 
This 
Is 
A 
Test}; 

while($data =~ /(.+)$/mg) { 
    print "line is '$1'\n"; 
} 

Bu bir dize temsil eden bir dosya tanıtıcısından kullanarak kıyasla biraz daha az kıvrık.

0
bölünmüş

iyi sonuç yapılabilir: Eğer arada ben de size eski moda gibi değişkenleri tanımlamak, tüm değişken başlatma bakmak önermek, en iyi uygulamalar hakkında konuşmak istiyorum yoksa

my $result="LINE1 
line2 
linE3 
"; 
#attention, /^/m allows properly operate on multiline string using regex 
#and^is character empty begin all lines 
foreach my $resultLine (split /^/m, $result) { 
    print $resultline; #withount '\n' because it have got 
    #some checks & operations 
} 
İlgili konular