2011-06-09 15 views
24

Dosya verildiğinde bir dosyaya yazılan hızlı bir komut dosyası veya herhangi bir dosya verilmediyse stdout yapmak istiyorum. Komut dosyasını, yeni bir dosya tanıtıcısı OUTFILE'ı işaret ederek, bunlardan hangisine uygun olursa, bunu yapmak benim için çok daha kolay olurdu.Dosya Kolunu Nasıl Perdeleyecek STDOUT (veya Başka Bir Dosya Kolu) Olarak İşaretlerim?

STDOUT'u uygun olduğunda çıkış dosyasına göndererek istediğimi gerçekleştirebileceğimi biliyorum, ancak bunu daha sonra komut dosyasını kullanarak kimseyi karıştırmak istemediğimi ve neden baskı ifadelerini merak ettiğimi yapmamayı tercih ederim çalışma Ayrıca, bazen sorun giderme amacıyla kendi ara sıra baskı bildirimini kullanmak istiyorum ve bu yazdırmayı asla çıkış dosyasına istemiyorum. Bu işe yaramazsa dışında
open(OUTFILE, ($output ? ">$output" : STDOUT);
: Bunun

tek şey için çizgisinde bir şeydir aradığım şey söyledi.

Fikirler?

cevap

37

bazı yollar (Neználkovo):

typeglob için bir referans olarak open için
# Requires 2-arg open, unfortunately 
open(OUTPUT, "> ".($output || '-')) or die; 

if ($output) { 
    open(OUTPUT, '>', $output) or die; 
} else { 
    *OUTPUT = *STDOUT; 
} 

if ($output) { 
    open(OUTPUT, '>', $output) or die; 
} else { 
    open(OUTPUT, '>&', \*STDOUT) or die; 
} 

bazı yollar (sözcük var):

# Requires 2-arg open, unfortunately 
open(my $fh, "> ".($output || '-')) or die; 

my $fh; 
if ($output) { 
    open($fh, '>', $output) or die; 
} else { 
    $fh = \*STDOUT; 
} 

my $fh; 
if ($output) { 
    open($fh, '>', $output) or die; 
} else { 
    open($fh, '>&', \*STDOUT) or die; 
} 

bazı yolları (diğer): Dediğim gibi

# Changes the default handle for <print "foo">. 
if ($output) { 
    open(OUTPUT, '>', $output) or die; 
    select(OUTPUT); 
} 
+2

'...} else {açık ($ fh, '> &'. Fileno (STDOUT)); } ' – mob

3

Normal çıktıyı her zaman STDOUT ve hata ayıklama ifadelerinize STDERR olarak yazabilirsiniz. Daha sonra kullanıcı çıktıların bir dosyaya gitmesini istiyorsa, STDOUT komut satırındaki dosyaya yeniden yönlendirebilir.

+0

, ben STDOUT dosyayı yönlendirebilirsiniz biliyorum, ama bu gerçekten oldukça olarak yapıyor önleyeceğini şeydir Diğerleri bunu yaparken kafa karıştırıcı ve can sıkıcı buluyorum ve daha sonra kodla başa çıkmak zorundayım. Son bir çığlık çabası olarak işe yarayacak, ancak daha çok daha temiz olacağını düşündüğümden, bir çıktı dosyasına ya da STDOUT'a farklı bir dosya tanıtıcısını yönlendirmeyi tercih ederim. – Eli

+3

@Eli - Bunu kodunuzda yapmak zorunda değilsiniz. Sadece yazınızı STDOUT'a yazdırmak için yazmanız yeterlidir. Bir kullanıcı komut dosyasını normal olarak çalıştırdığında, ekranda çıktıyı görecektir. Ama onlar da scriptname.pl> dosyaadı.txt 'yapabilirler, bu durumda betik çalışır ve çıktı 'filename.txt' dosyasında sona erer. STDERR'deki herhangi bir hata ayıklama kodu yine de konsolda görünecektir. Bu çoğu * nix yardımcı programları ve betikleri çalışır. –

+3

@Eli - Bu her turda en basit yaklaşımdır. Komut dosyanızda farklı çıkış yollarını bilen herhangi bir kodunuz yok. Kodda yaptığınız tek şey STDOUT'a yazılır. Kullanıcı, senaryoyu konsolda çıktıyı görmek isteyip istemediklerini veya bir dosyaya koyup koymayacağını veya hatta başka bir komutun STDIN'ini içine sokup yazmayacağını belirler. –

4

Nevermind. Anladım. Bir işareti atmak hile yapar. Tam çalışma kodu:

+3

Bu cevabı harika yapan şey, bunun nasıl çalıştığına dair bir açıklamadır. – Ether

7

- sihirdir. Sözleşmeyi izleyin veya en az sürpriz ilkesini ihlal ediyorsunuz.

use autodie qw(:all); 
use Getopt::Long qw(GetOptions); 
GetOptions(\my %opt, 'out=s') or die 'usage'; 
die 'usage' unless $opt{out}; 
open my $handle, ">$opt{out}"; 

perl foo -o blahblah  # opens file blahblah for writing 
perl foo -o -    # goes to STDOUT 

İlgili: Okuyucunun uğruna Are there reasons to ever use the two-argument form of open(...) in Perl?

10

(OP zaten "o çalışma var" beri):

Perl belgeleri, "perlopentut" (perldoc perlopentut) STDOUT'a yönlendirilmiş alternatif bir filehandle açmanın örneklerini verir, ancak bu bareword dosya elkitaplarını ve her ikisi de biraz eski olan open'un iki-arg versiyonunu kullanır. Damian Conway'in "Perl Best Practices" adlı kitabı (Damian'ın kitabına dayanan Perl :: Critic'in yanı sıra) üç arg açılışı ve sözcüksel dosya tanıtımı (my $foo style filehandles) kullanılmasını vurgular. Kromatik'in "Modern Perl" adlı eseri, kısaca, lexical dosya elemelerini kullanarak bahseder ve pratikte barlokları cesaretlendirir. Kabuk enjeksiyonlarına maruz kalmayı sınırlandırdığı için üç arg open, daha güvenli bir form olarak kabul edilir. Buradaki özel durum düşük riskli olsa da, hala üç argüman open için iyi bir alışkanlık haline gelmiştir.

O (perldoc açmak -f) Perl'in open belgelerinde gösterilen örneklerin dikkatle okunması alır ve biraz yorumlama üç-arg kullanırken STDOUT bir yinelenen filahandle yönettiği açılış ve işareti karakteri için doğru yerleşimi fark open sürümü. Birisi bunun işe yarayacağını varsayabilir: open my $fh, '>', '&STDOUT' or die $!;, çoğunlukla görmeye alıştığımız bir biçime benzediğinden (ve bir sembol isminin öncesindeki işareti). Fakat bu sözdizimi open'un ihtiyacı olmayan şey değildir ve onu tamamen farklı bir bağlamda görmeye alışkınızdır: belirli altprogramlar çağırır.

üç arg open ile STDOUT bir dupe açmak için doğru yolu, bu gibi > ve aynı ikinci argüman haline & birleştirmek, ve çıplak STDOUT bırakmaktır:

use Modern::Perl; 

open my $fh, '>&', STDOUT or die "Bleah: $!"; 

say $fh 'Printing alternate filehandle "$fh" worked.'; 
say 'Implicitly printing to "STDOUT" also works.'; 

Ya STDOUT geçen

open my $fh, '>&', \*STDOUT or ... 
İlgili konular