1String::Print(3) User Contributed Perl Documentation String::Print(3)
2
3
4
6 String::Print - printf alternative
7
9 ### Functional interface
10
11 use String::Print; # simpelest way
12 use String::Print qw/printi printp/, %config;
13 printi 'age {years}', years => 12;
14
15 # interpolation of arrays and hashes (serializers)
16 printi 'price-list: {prices}', prices => \@p, _join => "+";
17 printi 'dump: {c}', c => \%config;
18
19 # same with positional parameters
20 printp 'age %d", 12;
21 printp 'price-list: %.2f', \@prices;
22 printp 'dump: %s', \%settings;
23
24 # modifiers
25 printi 'price: {price%.2f}', price => 3.14*VAT*EURO;
26
27 # [0.91] more complex interpolation names
28 printi 'filename: {c.filename}', c => \%config;
29 printi 'username: {user.name}', user => $user_object;
30 printi 'price: {product.price €}', product => $db->product(3);
31
32 ### Object Oriented interface
33
34 use String::Print 'oo'; # import nothing
35 my $f = String::Print->new(%config);
36 $f->printi('age {years}', years => 12);
37 $f->printp('age %d', 12);
38
39 ### via Log::Report's __* functions (optional translation)
40
41 use Log::Report; # or Log::Report::Optional
42 print __x"age {years}", years => 12;
43
44 ### via Log::Report::Template (Template Toolkit extension)
45
46 [% SET name = 'John Doe' %]
47 [% loc("Dear {name},") %] # includes translation
48
50 This module inserts values into (format) strings. It provides "printf"
51 and "sprintf" alternatives via both an object oriented and a functional
52 interface.
53
54 Read in the "DETAILS" chapter below, why this module provides a better
55 alternative for printf(). Also, some extended examples can be found
56 down there. Take a look at them first, when you start using this
57 module!
58
60 The Object Oriented interface
61 See functions printi(), sprinti(), printp(), and sprintp(): you can
62 also call them as method.
63
64 use String::Print 'oo';
65 my $f = String::Print->new(%config);
66 $f->printi($format, @params);
67
68 # exactly the same functionality:
69 use String::Print 'printi', %config;
70 printi $format, @params;
71
72 The Object Oriented interface wins when you need the same configuration
73 in multiple source files, or when you need different configurations
74 within one program. In these cases, the hassle of explicitly using the
75 object has some benefits.
76
77 Constructors
78
79 String::Print->new(%options)
80 -Option --Default
81 encode_for undef
82 missing_key <warning>
83 modifiers [ qr/^%\S+/ = \&format_printf]>
84 serializers <useful defaults>
85
86 encode_for => HASH|'HTML'
87 [0.91] The format string and the inserted values will get encoded
88 according to some syntax rules. For instance, encode_entities()
89 of HTML::Entities when you specify the predefined string "HTML".
90 See encodeFor().
91
92 missing_key => CODE
93 [0.91] During interpolation, it may be discovered that a key is
94 missing from the parameter list. In that case, a warning is
95 produced and "undef" inserted. May can overrule that behavior.
96
97 modifiers => ARRAY
98 Add one or more modifier handlers to power of the formatter.
99 They will get preference over the predefined modifiers, but lower
100 than the modifiers passed to "print[ip]" itself.
101
102 serializers => HASH|ARRAY
103 How to serialize data elements.
104
105 example:
106
107 my $f = String::Print->new
108 ( modifiers => [ EUR => sub {sprintf "%5.2f e", $_[0]} ]
109 , serializers => [ UNDEF => sub {'-'} ]
110 , encode_for => 'HTML'
111 );
112
113 $f->printi("price: {p EUR}", p => 3.1415); # price: ␣␣3.14 e
114 $f->printi("count: {c}", c => undef); # count: -
115
116 Attributes
117
118 $obj->addModifiers(PAIRS)
119 The PAIRS are a combination of an selector and a CODE which
120 processes the value when the modifier matches. The selector is a
121 string or (preferred) a regular expression. Later modifiers with
122 the same name overrule earlier definitions. You may also specify
123 an ARRAY of modifiers per "print".
124
125 See section "Interpolation: Modifiers" about the details.
126
127 $obj->encodeFor(HASH|undef|($predefined, %overrule))
128 [0.91] Enable/define the output encoding. Read section "Output
129 encoding" about the details.
130
131 Printing
132
133 The following are provided as method and as function. You find their
134 explanation further down on this page.
135
136 $obj->printi([$fh], $format, PAIRS|HASH);
137
138 $obj->printp([$fh], $format, PAIRS|HASH);
139
140 $obj->sprinti($format, PAIRS|HASH);
141
142 $obj->sprintp($format, LIST, PAIRS);
143
145 The functional interface creates a hidden object. You may import any
146 of these functions explicitly, or all together by not specifying the
147 names.
148
149 . Example
150
151 use String::Print; # all
152 use String::Print 'sprinti'; # only sprinti
153
154 use String::Print 'printi' # only printi
155 , modifiers => [ EUR => sub {sprintf "%5.2f e", $_[0]} ]
156 , serializers => [ UNDEF => sub {'-'} ];
157
158 printi "price: {p EUR}", p => 3.1415; # price: ␣␣3.14 e
159 printi "count: {c}", c => undef; # count: -
160
161 printi( [$fh], $format, PAIRS|HASH )
162 Calls sprinti() to fill the data in PAIRS or HASH in $format, and
163 then sends it to the $fh (by default the selected file)
164
165 open my $fh, '>', $file;
166 printi $fh, ...
167
168 printi \*STDERR, ...
169
170 printp( [$fh], $format, PAIRS|HASH )
171 Calls sprintp() to fill the data in PAIRS or HASH in $format, and
172 then sends it to the $fh (by default the selected file)
173
174 sprinti($format, PAIRS|HASH|OBJECT)
175 The $format refers to some string, maybe the result of a
176 translation.
177
178 The PAIRS (which may be passed as LIST, HASH, or blessed HASH)
179 contains a mixture of special and normal variables to be filled in.
180 The names of the special variables (the options) start with an
181 underscore ("_").
182
183 -Option --Default
184 _append undef
185 _count undef
186 _join ', '
187 _prepend undef
188
189 _append => STRING|OBJECT
190 Text as STRING appended after $format, without interpolation.
191
192 _count => INTEGER
193 Result of the translation process: when Log::Report subroutine
194 __xn is are used for count-sensitive translation. Those function
195 may add more specials to the parameter list.
196
197 _join => STRING
198 Which STRING to use when an ARRAY is being filled-in as
199 parameter.
200
201 _prepend => STRING|OBJECT
202 Text as STRING prepended before $format, without interpolation.
203 This may also be an OBJECT which gets stringified, but variables
204 not filled-in.
205
206 sprintp($format, LIST, PAIRS)
207 Where sprinti() uses named parameters --especially useful when the
208 strings need translation-- this function stays close to the
209 standard sprintf(). All features of POSIX formats are supported.
210 This should say enough: you can use "%3$0#5.*d", if you like.
211
212 It may be useful to know that the positional $format is rewritten
213 and then fed into sprinti(). Be careful with the length of the
214 LIST: superfluous parameter PAIRS are passed along to sprinti(),
215 and should only contain "specials": parameter names which start
216 with '_'.
217
218 example: of the rewrite
219
220 # positional parameters
221 my $x = sprintp "dumpfiles: %s\n", \@dumpfiles
222 , _join => ':';
223
224 # is rewritten into, and then processed as
225 my $x = sprinti "dumpfiles: {_1}\n"
226 , _1 => \@dumpfiles, _join => ':';
227
229 Why use printi(), not printf()?
230 The printf() function is provided by Perl's CORE; you do not need to
231 install any module to use it. Why would you use consider using this
232 module?
233
234 translating
235 printf() uses positional parameters, where printi() uses names to
236 refer to the values to be filled-in. Especially in a set-up with
237 translations, where the format strings get extracted into PO-files,
238 it is much clearer to use names. This is also a disadvantage of
239 printp()
240
241 pluggable serializers
242 printi() supports serialization for specific data-types: how to
243 interpolate "undef", HASHes, etc.
244
245 pluggable modifiers
246 Especially useful in context of translations, the FORMAT string may
247 contain (language specific) helpers to insert the values correctly.
248
249 correct use of utf8
250 Sized string formatting in printf() is broken: it takes your string
251 as bytes, not Perl strings (which may be utf8). In unicode, one
252 "character" may use many bytes. Also, some characters are
253 displayed double wide, for instance in Chinese. The printi()
254 implementation will use Unicode::GCString for correct behavior.
255
256 automatic output encoding (for HTML)
257 You can globally declare that all produced strings must be encoded
258 in a certain format, for instance that HTML entities should be
259 encoded.
260
261 Four components
262 To fill-in a FORMAT, four clearly separated components play a role:
263
264 1. modifiers
265 How to change the provided values, for instance to hide locale
266 differences.
267
268 2. serializer
269 How to represent (the modified) the values correctly, for instance
270 "undef" and ARRAYs.
271
272 3. conversion
273 The standard UNIX format rules, like %d. One conversion rule has
274 been added 'S', which provides unicode correct behavior.
275
276 4. encoding
277 Prepare the output for a certain syntax, like HTML.
278
279 Simplified:
280
281 # sprinti() replaces "{$key$modifiers$conversion}" by
282 $encode->($format->($serializer->($modifiers->($args{$key}))))
283
284 # sprintp() replaces "%pos{$modifiers}$conversion" by
285 $encode->($format->($serializer->($modifiers->($arg[$pos]))))
286
287 Example:
288
289 #XXX Your manual-page reader may not support the unicode used
290 #XXX in the examples below.
291 printi "price: {price € %-10s}", price => $cost;
292 printi "price: {price € %-10s}", { price => $cost };
293 printp "price: %-10{€}s", $cost;
294
295 $value = $cost (in €)
296 $modifier = convert € to local currency £
297 $serializer = show float as string
298 $format = column width %-10s
299 $encode = £ into £ # when encodingFor('HTML')
300
301 Interpolation: keys
302 A key is a bareword (like a variable name) or a list of barewords
303 separated by dots (no blanks!)
304
305 Please use explanatory key names, to help the translation process once
306 you need that (in the future).
307
308 Simple keys
309
310 A simple key directly refers to a named parameter of the function or
311 method:
312
313 printi "Username: {name}", name => 'John';
314
315 You may also pass them as HASH or CODE:
316
317 printi "Username: {name}", { name => 'John' };
318 printi "Username: {name}", name => sub { 'John' };
319 printi "Username: {name}", { name => sub { 'John' } };
320 printi "Username: {name}", name => sub { sub {'John'} };
321
322 The smartness of pre-processing CODE is part of serialization.
323
324 Complex keys
325
326 [0.91] In the previous section, we kept our addressing it simple: let's
327 change that now. Two alternatives for the same:
328
329 my $user = { name => 'John' };
330 printi "Username: {name}", name => $user->{name}; # simple key
331 printi "Username: {user.name}", user => $user; # complex key
332
333 The way these complex keys work, is close to the flexibility of
334 template toolkit: the only thing you cannot do, is passing parameters
335 to called CODE.
336
337 You can pass a parameter name as HASH, which contains values. This may
338 even be nested into multiple levels. You may also pass objects, class
339 (package names), and code references.
340
341 In above case of "user.name", when "user" is a HASH it will take the
342 value which belongs to the key "name". When "user" is a CODE, it will
343 run code to get a value. When "user" is an object, the method "name"
344 is called to get a value back. When "user" is a class name, the "name"
345 refers to an instance method on that class.
346
347 More examples which do work:
348
349 # when name is a column in the database query result
350 printi "Username: {user.name}", user => $sth->fetchrow_hashref;
351
352 # call a sub which does the database query, returning a HASH
353 printi "Username: {user.name}", user => sub { $db->getUser('John') };
354
355 # using an instance method (object)
356 { package User;
357 sub new { bless { myname => $_[1] }, $_[0] }
358 sub name { $_[0]->{myname} }
359 }
360 my $user = User->new('John');
361 printi "Username: {user.name}", user => $user;
362
363 # using a class method
364 sub User::count { 42 }
365 printi "Username: {user.count}", user => 'User';
366
367 # nesting, mixing
368 printi "Complain to {product.factory.address}", product => $p;
369
370 # mixed, here CODE, HASH, and Object
371 printi "Username: {document.author.name}", document => sub {
372 return +{ author => User->new('John') }
373 };
374
375 Limitation: you cannot pass arguments to CODE calls.
376
377 Interpolation: Serialization
378 The 'interpolation' functions have named VARIABLES to be filled-in, but
379 also additional OPTIONS. To distinguish between the OPTIONS and
380 VARIABLES (both a list of key-value pairs), the keys of the OPTIONS
381 start with an underscore "_". As result of this, please avoid the use
382 of keys which start with an underscore in variable names. On the other
383 hand, you are allowed to interpolate OPTION values in your strings.
384
385 There is no way of checking beforehand whether you have provided all
386 values to be interpolated in the translated string. When you refer to
387 value which is missing, it will be interpreted as "undef".
388
389 strings
390 Simple scalar values are interpolated "as is"
391
392 CODE
393 When a value is passed as CODE reference, that function will get
394 called to return the value to be filled in. For interpolating, the
395 following rules apply:
396
397 SCALAR
398 Takes the value where the scalar reference points to.
399
400 ARRAY
401 All members will be interpolated with ",␣" between the elements.
402 Alternatively (maybe nicer), you can pass an interpolation
403 parameter via the "_join" OPTION.
404
405 printi "matching files: {files}", files => \@files, _join => ', '
406
407 HASH
408 By default, HASHes are interpolated with sorted keys,
409
410 $key => $value, $key2 => $value2, ...
411
412 There is no quoting on the keys or values (yet). Usually, this
413 will produce an ugly result anyway.
414
415 Objects
416 With the "serialization" parameter, you can overrule the
417 interpolation of above defaults, but also add rules for your own
418 objects. By default, objects get stringified.
419
420 serialization => [ $myclass => \&name_in_reverse ]
421
422 sub name_in_reverse($$$)
423 { my ($formatter, $object, $args) = @_;
424 # the $args are all parameters to be filled-in
425 scalar reverse $object->name;
426 }
427
428 Interpolation: Modifiers
429 Modifiers are used to change the value to be inserted, before the
430 characters get interpolated in the line. This is a powerful
431 simplification. Let's discuss this with an example.
432
433 In traditional (gnu) gettext, you would write:
434
435 printf(gettext("approx pi: %.6f\n"), PI);
436
437 to get PI printed with six digits in the fragment. Locale::TextDomain
438 has two ways to achieve that:
439
440 printf __"approx pi: %.6f\n", PI;
441 print __x"approx pi: {approx}\n", approx => sprintf("%.6f", PI);
442
443 The first does not respect the wish to be able to reorder the arguments
444 during translation (although there are ways to work around that) The
445 second version is quite long. The string to be translated differs
446 between the two examples.
447
448 With "Log::Report", above syntaxes do work as well, but you can also
449 do:
450
451 # with optional translations
452 print __x"approx pi: {pi%.6f}\n", pi => PI;
453
454 The base for "__x()" is the printi() provided by this module.
455 Internally, it will call "printi" to fill-in parameters:
456
457 printi "approx pi: {pi%.6f}\n", pi => PI;
458
459 Another example:
460
461 printi "{perms} {links%2d} {user%-8s} {size%10d} {fn}\n",
462 perms => '-rw-r--r--', links => 7, user => 'me',
463 size => 12345, fn => $filename;
464
465 An additional advantage (when you use translation) is the fact that not
466 all languages produce comparable length strings. Now, the translators
467 can change the format, such that the layout of tables is optimal for
468 their language.
469
470 Above example in printp() syntax, shorter but less maintainable:
471
472 printp "%s %2d %-8s 10d %s\n",
473 '-rw-r--r--', 7, 'me', 12345, $filename;
474
475 Interpolation: default modifiers
476 Default modifier: POSIX format
477
478 As shown in the examples above, you can specify a format. This can,
479 for instance, help you with rounding or columns:
480
481 printp "π = {pi%.3f}", pi => 3.1415;
482 printp "weight is {kilogram%d}", kilogram => 127*OUNCE_PER_KILO;
483 printp "{filename%-20.20s}\n", filename => $fn;
484
485 - improvements on POSIX format
486
487 The POSIX printf() does not handle unicode strings. Perl does
488 understand that the 's' modifier may need to insert utf8 so does not
489 count bytes but characters. printi() does not use characters but
490 "grapheme clusters" via Unicode::GCString. Now, also composed
491 characters do work correctly.
492
493 Additionally, you can use the new 'S' conversion to count in columns.
494 In fixed-width fonts, graphemes can have width 0, 1 or 2. For
495 instance, Chinese characters have width 2. When printing in fixed-
496 width, this 'S' is probably the better choice over 's'. When the field
497 does not specify its width, then there is no performance penalty for
498 using 'S'.
499
500 # name right aligned, commas on same position, always
501 printp "name: {name%20S},\n", name => $some_chinese;
502
503 Default modifier: BYTES
504
505 [0.91] Too often, you have to translate a (file) size into humanly
506 readible format. The "BYTES" modifier simplifies this a lot:
507
508 printp "{size BYTES} {fn}\n", fn => $fn, size => -s $fn;
509
510 The output will always be 6 characters. Examples are "999 B", "1.2
511 kB", and " 27 MB".
512
513 Default modifiers: YEAR, DATE, TIME, DT, and DT()
514
515 [0.91] A set of modifiers help displaying dates and times. They are a
516 little flexible in values they accept, but do not expect miracles: when
517 it get harder, you will need to process it yourself.
518
519 The actual treatment of a time value depends on the value: three
520 different situations:
521
522 1. numeric
523 A pure numeric value is considered "seconds since epoch", unless it
524 is smaller than 21000000, in which case it is taken as date without
525 separators.
526
527 2. date format without time-zone
528 The same formats are understood as in the next option, but without
529 time-zone information. The date is processed as text as if in the
530 local time zone, and the output in the local time-zone.
531
532 3. date format with time-zone
533 By far not all possible date formats are supported, just a few
534 common versions, like
535
536 2017-06-27 10:04:15 +02:00
537 2017-06-27 17:34:28.571491+02 # psql timestamp with zone
538 20170627100415+2
539 2017-06-27T10:04:15Z # iso 8601
540 20170627 # only for YEAR and DATE
541 2017-6-1 # only for YEAR and DATE
542 12:34 # only for TIME
543
544 The meaning of 05-04-2017 is unclear, so not supported.
545 Milliseconds get ignored.
546
547 When the provided value has a timezone indication, it will get
548 converted into the local timezone of the observer.
549
550 The output of "YEAR" is in format 'YYYY', for "DATE" it will always be
551 'YYYY-MM-DD', where "TIME" produces 'HH:mm:ss'.
552
553 The short form "DT" is an alias for DT(FT). The DT modifier can
554 produce different formats:
555
556 DT(ASC) : %a %b %e %T %Y asctime output
557 DT(FT) : %F %T YYYY-MM-DD HH:mm:ss
558 DT(ISO) : %FT%T%z iso8601
559 DT(RFC822) : %a, %d %b %y %T %z email old
560 DT(RFC2822) : %a, %d %b %Y %T %z email newer
561
562 You may suggest additional formats, or add your own modifier.
563
564 Default modifiers: //word, //"string", //'string'
565
566 [0.91] By default, an undefined value is shown as text 'undef'. Empty
567 strings are shown as nothing. This may not be nice. You may want to
568 be more specific when a value is missing.
569
570 "visitors: {count //0}"
571 "published: {date DT//'not yet'}"
572 "copyright: {year//2017 YEAR}
573
574 Modifiers will usually return "undef" when they are called with an
575 undefined or empty value. By the right order of '//', you may product
576 different kinds of output:
577
578 "price: {price//5 EUR}"
579 "price: {price EUR//unknown}"
580
581 Private modifiers
582
583 You may pass your own modifiers. A modifier consists of a selector and
584 a CODE, which is called when the selector matches. The selector is
585 either a string or a regular expression.
586
587 # in Object Oriented syntax:
588 my $f = String::Print->new
589 ( modifiers => [ qr/[€₤]/ => \&money ]
590 );
591
592 # in function syntax:
593 use String::Print 'printi', 'sprinti'
594 , modifiers => [ qr/[€₤]/ => \&money ];
595
596 # the implementation:
597 sub money$$$$)
598 { my ($formatter, $modif, $value, $args) = @_;
599
600 $modif eq '€' ? sprintf("%.2f EUR", $value+0.0001)
601 : $modif eq '₤' ? sprintf("%.2f GBP", $value/1.16+0.0001)
602 : 'ERROR';
603 }
604
605 Using printp() makes it a little shorter, but will become quite complex
606 when there are more parameter in one string.
607
608 printi "price: {p€}", p => $pi; # price: 3.14 EUR
609 printi "price: {p₤}", p => $pi; # price: 2.71 GBP
610
611 printp "price: %{€}s", $pi; # price: 3.14 EUR
612 printp "price: %{₤}s", $pi; # price: 2.71 GBP
613
614 This is very useful in the translation context, where the translator
615 can specify abstract formatting rules. As example, see the (GNU)
616 gettext files, in the translation table for Dutch into English. The
617 translator tells us which currency to use in the display.
618
619 msgid "kostprijs: {p€}"
620 msgstr "price: {p₤}"
621
622 Another example. Now, we want to add timestamps. In this case, we
623 decide for modifier names in "\w", so we need a blank to separate the
624 parameter from the modifer.
625
626 Modifiers: stacking
627
628 You can add more than one modifier. The modifiers detect the extend of
629 their own information (via a regular expression), and therefore the
630 formatter understands where one ends and the next begins.
631
632 The modifiers are called in order:
633
634 printi "price: {p€%9s}\n", p => $p; # price: ␣␣␣123.45
635 printi ">{t T%10s}<", t => $now; # >␣␣12:59:17<
636
637 printp "price: %9{€}s\n", $p; # price: ␣␣␣123.45
638 printp ">%10{T}s<", $now; # >␣␣12:59:17<
639
640 Output encoding
641 [0.91] This module is also used by Log::Report::Template, which is used
642 to insert (translated) strings with parameters into HTML templates.
643 You can imagine that some of the parameter may need to be encoded to
644 HTML in the template, and other not.
645
646 example with Log::Report::Template
647
648 In pure Template Toolkit, you would write
649
650 # in your TT-template
651 <div>Username: [% username | html %]</div>
652 # in your code
653 username => $user->name,
654
655 With plain String::Print with output encoding enabled, you can do:
656
657 # in your TT-template
658 <div>[% show_username %]</div>
659 # in your code with encodeFor('HTML')
660 show_username => printi("Username: {user}", user => $user->name),
661 # or
662 show_username => printp("Username: %s", $user->name),
663
664 That does not look very efficient, however it changes for the good when
665 this is combined with Log::Report::Lexicon (translations) You can
666 either do:
667
668 # in your TT-template
669 <div>[% show_username %]</div>
670 # in your code with encodeFor('HTML')
671 show_username => __x("Username: {user}", user => $user->name),
672
673 Shorter:
674
675 # in your TT-template with encodeFor('HTML')
676 <div>[% loc("Username: {user}", user => username) %]</div>
677 # in your code
678 username => $user->name,
679
680 Even shorter:
681
682 # in your TT-template with encodeFor('HTML')
683 <div>[% loc("Username: {user.name}", user => userobj) %]</div>
684 # in your code
685 userobj => $user,
686
687 Shortest:
688
689 # in your TT-template with encodeFor('HTML')
690 <div>[% loc("Username: {user.name}") %]</div>
691 # in your code
692 user => $user,
693
694 Shorter that the original, and translations for free! More examples in
695 Log::Report::Template.
696
697 Output encoding exclusion
698
699 In some cases, the data which is inserted is already encoded in the
700 output syntax. For instance, you already have HTML to be included.
701
702 The default exclusion rule for HTML output is "qr/html$/i", which means
703 that all inserted named parameters, where the name ends on "html" will
704 not get html-entity encoded.
705
706 This will work by default:
707
708 # with encodeFor('HTML')
709 printp "Me & Co: {name}, {description_html}",
710 name => 'René', description_html => $descr;
711
712 This may result in:
713
714 Me & Co: René, <font color="red">new member</font>
715
716 Better not to have HTML in your program: leave it to the template. But
717 in some cases, you have no choice.
718
719 Compared to other modules on CPAN
720 There are a quite a number of modules on CPAN which extend the
721 functionality of printf(). To name a few: String::Format
722 <http://search.cpan.org/~darren/String-Format>, String::Errf
723 <http://http://search.cpan.org/~rjbs/String-Errf>, String::Formatter
724 <http://http://search.cpan.org/~rjbs/String-Formatter>,
725 Text::Sprintf::Named <http://search.cpan.org/~shlomif/Text-Sprintf-
726 Named>, Acme::StringFormat <http://search.cpan.org/~gfuji/Acme-
727 StringFormat>, Text::sprintf <http://search.cpan.org/~sharyanto/Text-
728 sprintfn>, Log::Sprintf <http://search.cpan.org/~frew/Log-Sprintf>, and
729 String::Sprintf <http://search.cpan.org/~bartl/String-Sprintf>. They
730 are all slightly different.
731
732 When the "String::Print" module was created, none of the modules
733 mentioned above handled unicode correctly. Global configuration of
734 serializers and modifiers is also usually not possible, sometimes
735 provided per explicit function call. Only "String::Print" cleanly
736 separates the roles of serializers, modifiers, and conversions.
737
738 "String::Print" is nicely integrated with Log::Report.
739
741 This module is part of String-Print distribution version 0.94, built on
742 March 01, 2020. Website: http://perl.overmeer.net/CPAN/
743
745 Copyrights 2016-2020 by [Mark Overmeer <markov@cpan.org>]. For other
746 contributors see ChangeLog.
747
748 This program is free software; you can redistribute it and/or modify it
749 under the same terms as Perl itself. See http://dev.perl.org/licenses/
750
751
752
753perl v5.38.0 2023-07-21 String::Print(3)