2009-04-17 33 views
7

tôi cần phải sử dụng một số thay thế chuỗi trong Perl để giảm bớt dịch, tức là thay thế nhiềuTôi nên sử dụng gì thay vì printf trong Perl?

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

bởi một cái gì đó giống như

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

Tuy nhiên, tôi muốn thay thế printf với một cái gì đó dễ dàng hơn để phân tích cho con người, như thế này:

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

hoặc thường là một cái gì đó thêm Perly.

Bạn có thể đề xuất điều gì đó (từ CPAN hay không) mà bạn thích và sử dụng?

Trả lời

12

Hầu hết Templating mô-đun trên CPAN có thể sẽ làm những gì bạn muốn. Dưới đây là ví dụ sử dụng Template Toolkit ...

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

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


Và bạn có thể bắt chước ví dụ yêu cầu của bạn với một cái gì đó như thế này ...

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

và bạn đã có ...

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

Dường như bạn muốn có cách phân tích cú pháp các chuỗi khác nhau. Tôi sẽ khuyên bạn không nên làm điều này. Người duy nhất nhìn thấy cú pháp với% d trong đó là nhà phát triển và anh ta sẽ hiểu chính xác ý nghĩa của nó. Cú pháp printf mạnh mẽ vì các tùy chọn như phần đệm, số thập phân, v.v.

Tôi nghĩ bạn muốn sử dụng nhiều phương pháp thay thế hơn. Đó là perlish để làm s/{num}/$ n /.

+1

"Người duy nhất là người nhìn thấy cú pháp với% d trong nó là nhà phát triển "-> Đây không phải là trường hợp, những chuỗi đó sẽ được nhìn thấy bởi các dịch giả và những người khá câm quá :) Tôi muốn được tốt với printf bản thân mình nhưng tôi phải nghĩ khác mọi người ... –

1

Theo lời nhận xét của bạn về việc làm dịch giả, tôi đề nghị viết một kịch bản perl để cắt tất cả printf() và xếp chúng theo cách dễ dàng hơn với người dịch.

Something như thế này:

while(<>) 
{ 
    #regex for striping printf 

    #print in tabulated form 
} 

Nếu bạn in ra số dòng quá bạn có thể dễ dàng viết một chương trình khác để thay thế các văn bản dịch.

Giải pháp này sẽ không đưa bạn lâu hơn việc tính lại tiền từ printf() và có thể sử dụng lại.


Tôi chắc chắn sẽ gắn bó với printf(), đó là chuẩn trên nhiều ngôn ngữ.

Nó gần như đã trở thành một tiêu chuẩn cho đầu ra chuỗi. Giống như i là dành cho các vòng for.

+0

Tôi sử dụng "vòng lặp" :-) –

+3

Vấn đề với printf là bạn cũng phải nhận được thứ tự đúng. Nghĩa là, nếu một ngôn ngữ đảo ngược thứ tự của các mục được thay thế, thì người dịch là SOL với một số printf (ví dụ, C). Để dịch dễ dàng hơn, bạn cần sử dụng "% 1 $ d" để chúng có thể dễ dàng di chuyển nó. Bộ công cụ mẫu làm cho điều này tầm thường. – Tanktalus

14

gì về đơn giản:

print "Outputting $n numbers"; 

Đó là rất Perly. Nếu bạn không cần bất kỳ loại định dạng ưa thích, nội suy chuỗi chắc chắn là con đường để đi.

+0

Cảm ơn gợi ý, đây là ý tưởng phù hợp trong hầu hết các trường hợp tôi đoán, tuy nhiên tôi không luôn luôn xuất các biến nội suy (Dumper (\% băm) xuất hiện trong đầu). Phải xem nó hoạt động như thế nào, nhưng có lẽ tôi cần một thứ linh hoạt hơn một chút ... –

+3

Có một thành ngữ để xuất các biểu thức tùy ý trong nội suy: in "Hash là: @ {[Dumper (\% hash)]}"; Nó không đẹp nhưng nó hoạt động. –

+0

@Greg Hewgill Tôi không biết bạn có thể làm được điều này - tuyệt vời! – cowgod

-2

well, perl có printf chức năng ... chờ, bạn có muốn một cái gì đó như python's string formatting with dict?

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

mmm, tôi không biết điều gì đó như thế tồn tại trong perl ... ít nhất là không này "dễ dàng" ... lẽ Text::Sprintf::Named có thể là bạn của bạn

+0

Trong trường hợp nó không rõ ràng, tôi muốn sử dụng một cái gì đó thay vì printf của Perl, không phải printf của C. –

5

Các print dựng sẵn là rất thuận tiện cho hầu hết các tình huống. Bên cạnh đó suy biến:

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

Hãy nhớ rằng print có thể mất nhiều tranh cãi, do đó không cần phải nối chúng đầu tiên vào một chuỗi duy nhất nếu bạn cần in kết quả của một cuộc gọi chương trình con:

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

Tuy nhiên, để xuất các số khác với số nguyên đơn giản, có thể bạn sẽ muốn tiện ích định dạng của printf. Tuy nhiên, việc xuất các loại dữ liệu khác rất dễ dàng với print.

Bạn có thể sử dụng join để mảng thuận tiện đầu ra:

print join ', ', @array; 

Và kết hợp với mapkeys để băm đầu ra:

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

Sử dụng các nhà điều hành qq nếu bạn muốn trích dẫn ra xung quanh dữ liệu :

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

Nếu bạn muốn giảm bớt bản dịch, bạn nên cân nhắc sử dụng một trong các mô-đun CPAN L10n/i18n có sẵn. Cụ thể, một tổng quan tốt về lý do tại sao phương pháp tiếp cận của bạn sẽ kết thúc giảm ngắn là written up as part of the Local::Maketext docs.

Một mô-đun tuyệt vời khác kết hợp độc đáo với Locale :: Maketext là Locale::Maketext::Lexicon. Điều này cho phép bạn sử dụng các định dạng bản địa hóa chuẩn hơn như tệp .po/.mo của gettext có các công cụ GUI để giúp người dịch làm việc thông qua tất cả văn bản cần dịch. Locale :: Maketext :: Lexicon cũng đi kèm với một kịch bản trợ giúp (xgettext.pl) giúp giữ cho các tập tin bản địa hóa của bạn được cập nhật với các mẫu hoặc các mô-đun có văn bản cần dịch. Tôi đã có kết quả rất tốt với loại thiết lập này trong quá khứ.

+0

Tôi không nói về i18n ở đây (ngoài L :: M :: Lexicon hoàn toàn không phù hợp, nhiều hơn thế nữa;)), mà là chuẩn bị các chuỗi để dịch. Tại công việc của tôi, chúng tôi hiện đang phải sử dụng một hệ thống dịch thuật tùy chỉnh, nơi các chuỗi được trích xuất một cách kỳ lạ. –

1

Nói chung trả lời từ Draegtun là rất tốt, nhưng nếu bạn cần một cái gì đó nhỏ hơn (tức là ít bộ nhớ), và không phải là mạnh mẽ mà bạn có thể dễ dàng làm điều đó sử dụng chức năng này:

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; 
} 
Các vấn đề liên quan