Что я должен использовать вместо printf в Perl? - PullRequest
7 голосов
/ 17 апреля 2009

Мне нужно использовать некоторую замену строк в Perl, чтобы упростить переводы, т.е. заменить многие

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

чем-то вроде

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

Тем не менее, я хотел бы заменить printf на что-то более простое для разбора для людей, например:

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

или вообще что-то более перли.

Можете ли вы порекомендовать что-то (из CPAN или нет), что вам нравится и используется?

Ответы [ 8 ]

14 голосов
/ 17 апреля 2009

А как же просто:

 print "Outputting $n numbers";

Это очень Перли. Если вам не нужно какое-либо необычное форматирование, то, безусловно, лучше всего использовать интерполяцию строк.

12 голосов
/ 17 апреля 2009

Большинство шаблонных модулей в CPAN, вероятно, будут делать то, что вы хотите. Вот пример использования Template Toolkit ...

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

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


И вы можете имитировать нужный вам пример с чем-то вроде этого ...

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

и у вас есть ...

printX 'Outputting {num} numbers' => { num => 100 };
5 голосов
/ 17 апреля 2009

Если вы хотите облегчить перевод, вам следует рассмотреть возможность использования одного из доступных модулей CPAN L10n / i18n. В частности, хороший обзор того, почему ваш подход потерпит неудачу, написан как часть документации Local :: Maketext .

Еще один замечательный модуль, который прекрасно сочетается с Locale :: Maketext: Locale :: Maketext :: Lexicon . Это позволяет вам использовать более стандартные форматы локализации, такие как файлы .po / .mo gettext, которые имеют инструменты GUI, чтобы помочь переводчикам работать со всем текстом, который требуется перевести. Locale :: Maketext :: Lexicon также поставляется со вспомогательным скриптом (xgettext.pl), который помогает поддерживать ваши файлы локализации в актуальном состоянии с вашими шаблонами или модулями, которые имеют текст, который необходимо перевести. У меня были очень хорошие результаты с такой установкой в ​​прошлом.

5 голосов
/ 17 апреля 2009

Встроенный print очень удобен для большинства ситуаций. Помимо переменной интерполяции:

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

Помните, что print может принимать несколько аргументов, поэтому нет необходимости сначала объединять их в одну строку, если вам нужно вывести результат вызова подпрограммы:

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

Однако для вывода чисел, отличных от простых целых, вам, вероятно, понадобится удобство форматирования printf. Вывести другие типы данных легко с помощью print.

Вы можете использовать join для удобного вывода массивов:

print join ', ', @array;

И объединить с map и keys для вывода хэшей:

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

Используйте оператор qq, если вы хотите выводить кавычки вокруг данных:

print join ', ', map {qq("$_" : "$hash{$_}"}) keys %hash;
4 голосов
/ 17 апреля 2009

Кажется, вы хотите иметь другой способ анализа строк. Я бы посоветовал вам не делать этого. Единственный, кто видит синтаксис с% d в нем, является разработчиком, и он точно поймет, что имеется в виду. Синтаксис printf является мощным из-за таких опций, как padding, decimals и т. Д.

Я думаю, вы хотите использовать больше метод замены. Это правильно делать s / {num} / $ n /.

1 голос
/ 17 апреля 2009

Как правило, ответ от Draegtun отличный, но если вам нужно что-то меньшее (т.е. меньше памяти), и не настолько мощное, вы можете легко сделать это с помощью этой функции:

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;
}
1 голос
/ 17 апреля 2009

В свете вашего комментария о том, что вы для переводчиков, я предлагаю написать Perl-скрипт, который удаляет все printf() и табулирует их в более удобной для переводчиков форме.

Примерно так:

while(<>)
{
    #regex for striping printf

    #print in tabulated form
}

Если вы также напечатаете номер строки, вы можете легко написать другую программу для замены переведенного текста.

Это решение не займет у вас больше времени, чем перефакторинг от printf(), и его можно использовать повторно.


Я бы определенно придерживался printf(), это стандарт для многих языков.

Это почти стало стандартом для строкового вывода. Как i для for петель.

0 голосов
/ 17 апреля 2009

хорошо, Perl имеет printf функцию ... подождите, вы хотите что-то вроде форматирования строки python с помощью dict ?

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

ммм, я не знаю, что-то подобное существует в Perl ... по крайней мере, не это "легко" ... возможно Текст :: Sprintf :: Named может быть вашим другом

...