2009-04-17 14 views
7

Ben çeviriler hafifletmek için Perl bazı dize değiştirme kullanmak gerekir, yani AncakPerl'de printf yerine ne kullanmalıyım?

printf ("Outputting %d numbers", $n); 

gibi bir şey ile birçok

print "Outputting " . $n . " numbers"; 

yerine, ben ayrıştırılması daha kolay bir şey ile printf değiştirmek istediğiniz Bu gibi insanlar:

printX ("Outputting {num} numbers", { num => $n }); 

veya genelde daha fazla bir şey.

Beğendiğiniz ve kullandığınız bir şey (CPAN'dan değil) önerebilir misiniz?

cevap

12

En şablonu modülleri CPAN Muhtemelen istediğini yapacaksın. İşte Template Toolkit kullanarak bir örnek ...

use Template; 
my $tt = Template->new; 

$tt->process(\"Outputting [% num %] numbers\n", { num => 100 }); 


Ve böyle bir şey ile gerekli örnek taklit edebilir ...

sub printX { 
    use Template; 
    my $tt = Template->new(START_TAG => '{', END_TAG => '}'); 
    $tt->process(\($_[0] . "\n"), $_[1]); 
} 

ve var ...

printX 'Outputting {num} numbers' => { num => 100 }; 
4

Dizeleri ayrıştırmanın farklı bir yoluna sahip olmak istediğiniz görünüyor. Bunu yapmamanı tavsiye ederim. Sözdizimini% d ile görebilen tek kişi geliştiricidir ve tam olarak ne anlama geldiğini anlayacaktır. Printf sözdizimi, dolgu, ondalık vb. Gibi seçenekler nedeniyle güçlüdür.

Daha çok bir değiştirme yöntemi kullanmak istediğinizi düşünüyorum. S/{num}/$ n/yapmak doğrudur.

+1

"tek kim % d ile sözdizimini görmek geliştiricidir "-> Bu durum böyle değildir, bu dizeler çevirmenler ve oldukça aptal olanlar tarafından da görülecektir :) Kendimden basmakla iyi olurum ama diğerlerini düşünmek zorundayım insanlar ... –

1

Çevirmen olmanın hakkındaki yorumunuzun ışığında, tüm printf()'u kuran ve bunları daha kolay çevirmen dostu bir şekilde etiketleyen bir perl komut dosyası yazmanızı öneririm. Böyle

şey: hattan çıktısını Eğer

while(<>) 
{ 
    #regex for striping printf 

    #print in tabulated form 
} 

çok kolayca çevrilmiş metni değiştirmek için başka bir program yazabilirsiniz.

Bu çözüm, printf()'dan yeniden faktoring yapmanıza gerek kalmaz ve yeniden kullanılabilir. Kesinlikle printf() sopa ile olur


, birçok diller arasında standart.

Neredeyse dizi çıkışı için bir standart haline gelmiştir. i gibi for döngüleri içindir.

+0

"loop" :-) kullanıyorum :-) –

+3

printf ile ilgili sorun da siparişi doğru almanız gerektiğidir. Yani, bir dil, değiştirilmekte olan öğelerin sırasını tersine çevirirse, çevirmen bazı printf'ler ile SOL'tur (C). Çeviriyi daha kolay hale getirmek için "% 1 $ d" yi kullanmanız gerekir, böylece kolayca taşıyabilirler. Şablon Araç Seti bu önemsiz hale getirir. – Tanktalus

14

Ne basitçe hakkında: çok Perly var

print "Outputting $n numbers"; 

. Herhangi bir fantezi biçimlendirmeye ihtiyacınız yoksa, string interpolasyon kesinlikle gitmek için bir yoldur.

+0

Öneriniz için teşekkürler, bu çoğu durumda uygun bir fikir sanırım, ancak her zaman enterpolasyonu değişkenler vermiyorum (Dumper (\% hash) akla geliyor). Bunun nasıl çalıştığını görmek zorundayım ama muhtemelen biraz daha esnek bir şeye ihtiyacım var. –

+3

Enterpolasyonda keyfi ifadeler çıkaran bir deyim var: print "Hash is: @ {[Dumper (\% hash)]}"; Güzel değil ama işe yarıyor. –

+0

@Greg Hewgill Bunu yapabileceğiniz hakkında hiçbir fikrim yoktu - harika! – cowgod

-2

well, perl printf işlevinde ... wait, python's string formatting with dict gibi bir şey ister misiniz?

>>> print '%(key)s' % {'key': 'value'} 
value 

mmm, ben ... perl'de var böyle bir şey bilmiyorum en azından ... belki Text::Sprintf::Named arkadaşınız olabilir bu "kolay"

+0

Açık olmadığı takdirde, C'nin printf'i değil, Perl'in printf yerine bir şey kullanmak istiyorum. –

5

print yerleşik çok olduğu çoğu durum için uygun. Değişken interpolasyon yanında:

print "Outputting $n numbers"; # These two lines 
print "Outputting ${n} numbers"; # are equivalent 

print birden fazla argüman sürebileceğini unutmayın, böylece bir alt yordam çağrısı sonucu yazdırmak gerekiyorsa tek bir dize halinde onları ilk bağlamak için gerek yoktur:

print "Output data: ", Dumper($data); 

Ancak, basit tamsayılar dışındaki sayıları çıktı almak için muhtemelen printf formatlama kolaylığını isteyeceksiniz. Diğer veri türlerinin çıktısı ise print ile çok kolaydır.

Sen join elverişli çıktı diziler kullanabilirsiniz:

print join ', ', @array; 

Ve çıkış sağlamalarının map ve keys ile birleştirmek: Veri etrafında çıkış tırnak için isterseniz

print join ', ', map {"$_ : $hash{$_}"} keys %hash; 

Kullanım qq operatör :

print join ', ', map {qq("$_" : "$hash{$_}"}) keys %hash; 
5

Çevirileri kolaylaştırmak istiyorsanız, mevcut olan L10n/i18n CPAN modüllerinden birini kullanmayı düşünmelisiniz. Spesifik olarak, yaklaşımınızın neden kısa düşeceği hakkında iyi bir genel bakış written up as part of the Local::Maketext docs'dur.

Locale :: Maketext ile güzelce eşleşen bir başka harika modül ise Locale::Maketext::Lexicon. Bu, çevirmenlerin çeviri gerektiren tüm metinleri kullanmasına yardımcı olmak için GUI araçlarına sahip gettext'in .po/.mo dosyaları gibi daha standart yerelleştirme biçimlerini kullanmanıza olanak tanır. Locale :: Maketext :: Lexicon ayrıca, yerelleştirme dosyalarınızı, çeviri gerektiren metne sahip şablonlarınız veya modüllerle güncel tutmanıza yardımcı olan bir yardımcı komut dosyası (xgettext.pl) ile birlikte gelir. Geçmişte bu tür bir kurulumla çok iyi sonuçlar aldım.

+0

Burada i18n hakkında konuşmuyorum (L :: M :: Lexicon'dan tamamen uygun değil, daha sonraya;)), ancak çeviri için dizeleri hazırlayın. Çalışmamda, dizelerin garip bir şekilde çıkarıldığı özel bir çeviri sistemi kullanmak zorundayız. –

1

Genellikle Draegtun gelen cevap harika ama daha küçük bir şey (yani daha az bellek) ve kolayca bu fonksiyon kullanılarak yok gibi güçlü değil ihtiyacım olacağını eğer:

sub printX { 
    my ($format, $vars) = @_; 

    my @sorted_keys = sort { length($b) <=> length($a) } keys %{ $vars }; 
    my $re = join '|', map { "\Q$_\E" } @sorted_keys; 

    $format =~ s/ \{ \s* ($re) \s* \} /$vars->{$1}/xg; 

    print $format; 
}