2009-04-17 19 views
7

que necesitan valerse de sustitución de cadenas en Perl para facilitar la traducción, es decir, sustituir muchas¿Qué debo usar en lugar de printf en Perl?

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

por algo así como

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

Sin embargo, me gustaría reemplazar printf con algo más fácil de analizar para humanos, como este:

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

o en general algo más Perly.

¿Puede recomendar algo (de CPAN o no) que le guste y use?

Respuesta

12

módulos más Templating en CPAN probablemente haga lo que quiera. Aquí hay un ejemplo usando Template Toolkit ...

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

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


Y se puede imitar su ejemplo requerido con algo como esto ...

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

y tienes ...

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

Parece que desea tener una forma diferente de analizar cadenas. Te aconsejo que no hagas esto. El único que ve la sintaxis con el% d en él es el desarrollador y él entenderá exactamente lo que significa. La sintaxis de printf es poderosa debido a las opciones como relleno, decimales, etc.

Creo que desea utilizar más un método de reemplazo. Es perlish hacer s/{num}/$ n /.

+1

"El único que es ver la sintaxis con el% d en él es el desarrollador "-> Este no es el caso, esas cadenas serán vistos por los traductores y los muy tontos también :) Estaría bien con printf pero tengo que pensar en otra personas ... –

1

A la luz de su comentario acerca de ser para traductores, sugiero escribir un script en perl que elimine todos los printf() y los tabula de una manera más sencilla y fácil de traducir.

Algo como esto:

while(<>) 
{ 
    #regex for striping printf 

    #print in tabulated form 
} 

Si imprime el número de línea también se puede escribir fácilmente otro programa para sustituir el texto traducido.

Esta solución no le tomará más tiempo que volver a factorizar lejos de printf() y es reutilizable.


definitivamente me gustaría seguir con printf(), que es estándar en muchos idiomas.

Se ha convertido casi en un estándar para la salida de cuerdas. Como i es para for bucles.

+0

Uso "loop" :-) –

+3

El problema con printf es que también tiene que hacer el pedido correctamente. Es decir, si un idioma invierte el orden de los elementos que se sustituyen, el traductor es SOL con algunos printf (por ejemplo, C). Para facilitar la traducción, debe usar "% 1 $ d" para que puedan moverse fácilmente. Template Toolkit lo hace trivial. – Tanktalus

14

¿Qué pasa simplemente:

print "Outputting $n numbers"; 

Eso es muy Perly. Si no necesita ningún tipo de formato elegante, la interpolación de cadenas definitivamente es el camino a seguir.

+0

Gracias por la sugerencia, esta es una idea adecuada en la mayoría de los casos, sin embargo, no siempre me sale variables interpolables (me viene a la mente el Dumper (\% hash)). Tengo que ver cómo funciona, pero probablemente necesite algo un poco más flexible ... –

+3

Hay una expresión idiomática para generar expresiones arbitrarias en interpolación: print "Hash is: @ {[Dumper (\% hash)]}"; No es bonito, pero funciona. –

+0

@Greg Hewgill No tenía idea de que pudieras hacer esto, ¡increíble! – cowgod

-2

bueno, perl tiene printf función ... espera, ¿quieres algo así como python's string formatting with dict?

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

mmm, no sé algo así existir en Perl ... al menos no esta "fácil" ... tal vez Text::Sprintf::Named puede ser su amigo

+0

En caso de que no fuera claro, me gustaría usar algo en lugar del printf de Perl, no el printf de C. –

5

la orden interna es muy print conveniente para la mayoría de las situaciones. Además de la interpolación de variables:

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

Recuerde que print puede tomar varios argumentos, así que no hay necesidad de concatenar primero en una sola cadena si es necesario imprimir el resultado de una llamada a subrutina:

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

Sin embargo, para generar números que no sean números enteros simples, es probable que desee la conveniencia de formato de printf. La salida de otros tipos de datos es fácil con print, sin embargo.

Puede utilizar join a matrices convenientemente de salida:

print join ', ', @array; 

y se combinan con map y keys a los hashes de salida:

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

Use el operador qq si quieres cotizaciones de salida alrededor de los datos :

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

Si busca facilitar las traducciones, debería considerar usar uno de los módulos CPAN L10n/i18n que están disponibles. Específicamente, una buena descripción de por qué su enfoque terminará por quedarse corto es written up as part of the Local::Maketext docs.

Otro gran módulo que combina muy bien con Locale :: Maketext es Locale::Maketext::Lexicon. Esto le permite utilizar formatos de localización más estándar, como los archivos .po/.mo de gettext que tienen herramientas de GUI para ayudar a los traductores a trabajar a través de todo el texto que necesita traducción. Locale :: Maketext :: Lexicon también viene con un script de ayuda (xgettext.pl) que ayuda a mantener sus archivos de localización actualizados con sus plantillas o módulos que tienen texto que necesitan traducción. He tenido muy buenos resultados con este tipo de configuración en el pasado.

+0

No estoy hablando de i18n aquí (aparte de que L :: M :: Lexicon es completamente inadecuado, más para eso más tarde;)), sino más bien de preparar cadenas para la traducción. En mi trabajo, actualmente tenemos que usar un sistema de traducción personalizado donde las cadenas se extraen de una manera extraña. –

1

responder general de Draegtun es grande, pero si lo que se necesita algo más pequeño (es decir, menos memoria), y no es tan poderoso que fácilmente lo puede hacer uso de esta función:

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; 
} 
Cuestiones relacionadas