2012-08-30 21 views
6

STDIN'den birkaç satır okurum. STDIN'in kalanını standart girişten (örn. md5sum veya wc) okuyan bir komuta nasıl aktarabilirim?Perl: Açık dosya tanıtıcısını bir program okumasına geçirin STDIN

Ben yapabileceği:

read_a_few_lines_from_diamond_operator(); 
open (C, "|cmd"); 
while(<>) { print C } 
close C; 
cleanup_after_C(); 

ama verime nedenlerle ben dokunmatik giriş, ancak bunun yerine STDIN ait dosya tanıtıcısından geçmek değil istiyorum. Sayılır gibi: wc üzerine kalanını geçirmeden önce sever gibi read kadar okur

seq 10 | (read A; wc) 

. Yine de bu çözümü kullanamıyorum, çünkü perl programımın içinden komutu başlatmam gerekiyor ve ben de cmd tamamlandıktan sonra iş yapmam gerekiyor.


'foo' dosyasından birkaç satır okurum. Kalanı standart girişten okuyan bir komuta nasıl iletebilirim (ör. md5sum veya wc)?

Ben yapabileceği:

open (F, "<foo"); 
read_a_few_lines_from_F(); 
open (C, "|cmd"); 
while(<F>) { print C } 
close C; 
cleanup_after_C(); 

ama verime nedenlerle ben dokunmatik giriş, ancak bunun yerine dosya 'foo' kalanını geçirmek için değil istiyorum.


Ben select, open(FOO,">&STDOUT), exec 6<&0, fork, pipe gibi hile kullanarak yapılması can bir his var.

cevap

8

Cevap oldukça basit: Özel bir şey yapmanıza gerek yok. Çocuğunuz STDIN'u ve exec ile otomatik olarak devralır. STDIN'den okumadığınız her şey çocuk tarafından okunabilir.

Ancak bir sorun var. Bir kerede bir karakterin okunması çılgın verimsiz olacağından, Perl dosyadan her seferinde bir blok okur. Diğer bir deyişle, dosyadan Perl'den geri döndüğünüz "birkaç satır" dan daha fazlasını okuyorsunuz. Bu açıkça aşağıdaki komutu kullanarak görülebilir: Yerine ikinci satırın başında başlayan

perl -E'say $_ x 500 for "a".."z"' \ 
    | perl -e'<>; <>; exec("cat");' \ 
    | less 

, (bayt 8192 at) "q" s ortasında cat başlar!

readline (<>) ile okuma satırlarından, çalışmasını istiyorsanız, tek tek baytları sysread ile okumak zorundasınız. hatta belki

open(STDIN, "<", "foo") or die $!; 
read_a_few_lines(*STDIN); 
my $pos = tell(STDIN); 
open(STDIN, "<", "foo") or die $!; 
sysseek(STDIN, $pos, SEEK_SET); 
system(@cmd); 
... 

Veya:

open(STDIN, "<", "foo") or die $!; 
read_a_few_lines(*STDIN); 
sysseek(STDIN, tell(STDIN), SEEK_SET); 
system(@cmd); 
... 

Untested büyük resimde üzerinde yoğunlaşırken


, bir çözüm olduğunu düşünüyorum.

+0

Size bir başparmak kazandıran, ancak 2 problemi olan zarif bir çözüm: Perl'i öldürür (bunun benim için işe yaramayacağını açıkça belirterek soruyu açıklığa kavuşturdum); ve 2. bölümle ilgilenmiyor ('foo' dosyasını okuyor). –

+0

Neden çalışmıyor? Cevabın dediği gibi, “sistem” in yanı sıra “exec” için de çalışıyor. 'Perl -e' yazdırıyor <>; Sistem ("CAT"); "hala burada \ n" "yazdır" yazdı, senaryonuzun çıplak kemiklerini göstermiyor musunuz? – tripleee

+0

Çok iyi tespit edildi. Bu çalışır: seq 10 | perl -e 'sysread (STDIN, $ a, 1); "$ a bar", sistem ("kedi") yazdırmak; "hala burada \ n" yazdı. Yine de 'foo' dosyasını okumaya devam ediyor. –

İlgili konular