Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
String::Print(3)      User Contributed Perl Documentation     String::Print(3)

       String::Print - printf alternative

	 ### Functional	interface

	 use String::Print;	      #	simpelest way
	 use String::Print qw/printi printp/, %config;
	 printi	'age {years}', years =>	12;

	 # interpolation of arrays and hashes (serializers)
	 printi	'price-list: {prices}',	prices => \@p, _join =>	"+";
	 printi	'dump: {c}', c => \%config;

	 # same	with positional	parameters
	 printp	'age %d", 12;
	 printp	'price-list: %.2f', \@prices;
	 printp	'dump: %s', \%settings;

	 # modifiers
	 printi	'price:	{price%.2f}', price => 3.14*VAT*EURO;

	 # [0.91] more complex interpolation names
	 printi	'filename: {c.filename}', c => \%config;
	 printi	'username: {}', user => $user_object;
	 printi	'price:	{product.price a~}', product =>	$db->product(3);

	 ### Object Oriented interface

	 use String::Print 'oo';      #	import nothing
	 my $f = String::Print->new(%config);
	 $f->printi('age {years}', years => 12);
	 $f->printp('age %d', 12);

	 ### via Log::Report's __* functions (optional translation)

	 use Log::Report;	      #	or Log::Report::Optional
	 print __x"age {years}", years => 12;

	 ### via Log::Report::Template (Template Toolkit extension)

	 [% SET	name = 'John Doe' %]
	 [% loc("Dear {name},")	%]     # includes translation

       This module inserts values into (format)	strings.  It provides "printf"
       and "sprintf" alternatives via both an object oriented and a functional

       Read in the "DETAILS" chapter below, why	this module provides a better
       alternative for "printf()".  Also, some extended	examples can be	found
       down there.  Take a look	at them	first, when you	start using this

   The Object Oriented interface
       See functions printi(), sprinti(), printp(), and	sprintp(): you can
       also call them as method.

	 use String::Print 'oo';
	 my $f = String::Print->new(%config);
	 $f->printi($format, @params);

	 # exactly the same functionality:
	 use String::Print 'printi', %config;
	 printi	$format, @params;

       The Object Oriented interface wins when you need	the same configuration
       in multiple source files, or when you need different configurations
       within one program.  In these cases, the	hassle of explicitly using the
       object has some benefits.


	    -Option	--Default
	     encode_for	  undef
	     missing_key  <warning>
	     modifiers	  [ qr/^%\S+/ =	\&format_printf]>
	     serializers  <useful defaults>

	   encode_for => HASH|'HTML'
	     [0.91] The	format string and the inserted values will get encoded
	     according to some syntax rules.  For instance,
	     "encode_entities()" of HTML::Entities when	you specify the
	     predefined	string "HTML".	See encodeFor().

	   missing_key => CODE
	     [0.91] During interpolation, it may be discovered that a key is
	     missing from the parameter	list.  In that case, a warning is
	     produced and "undef" inserted.  May can overrule that behavior.

	   modifiers =>	ARRAY
	     Add one or	more modifier handlers to power	of the formatter.
	     They will get preference over the predefined modifiers, but lower
	     than the modifiers	passed to "print[ip]" itself.

	   serializers => HASH|ARRAY
	     How to serialize data elements.


	     my	$f = String::Print->new
	       ( modifiers   =>	[ EUR	=> sub {sprintf	"%5.2f e", $_[0]} ]
	       , serializers =>	[ UNDEF	=> sub {'-'} ]
	       , encode_for  =>	'HTML'

	     $f->printi("price:	{p EUR}", p => 3.1415);	# price: aLaL3.14 e
	     $f->printi("count:	{c}", c	=> undef);	# count: -


	   The PAIRS are a combination of an selector and a CODE which
	   processes the value when the	modifier matches.  The selector	is a
	   string or (preferred) a regular expression. Later modifiers with
	   the same name overrule earlier definitions.	You may	also specify
	   an ARRAY of modifiers per "print".

	   See section "Interpolation: Modifiers" about	the details.

       $obj->encodeFor(HASH|undef|($predefined,	%overrule))
	   [0.91] Enable/define	the output encoding.  Read section "Output
	   encoding" about the details.


       The following are provided as method and	as function.  You find their
       explanation further down	on this	page.

       $obj->printi([$fh], $format, PAIRS|HASH);

       $obj->printp([$fh], $format, PAIRS|HASH);

       $obj->sprinti($format, PAIRS|HASH);

       $obj->sprintp($format, LIST, PAIRS);

       The functional interface	creates	a hidden object.  You may import any
       of these	functions explicitly, or all together by not specifying	the

       . Example

	 use String::Print;	      #	all
	 use String::Print 'sprinti'; #	only sprinti

	 use String::Print 'printi'   #	only printi
	   , modifiers	 => [ EUR   => sub {sprintf "%5.2f e", $_[0]} ]
	   , serializers => [ UNDEF => sub {'-'} ];

	 printi	"price:	{p EUR}", p => 3.1415; # price:	aLaL3.14 e
	 printi	"count:	{c}", c	=> undef;      # count:	-

       printi( [$fh], $format, PAIRS|HASH )
	   Calls sprinti() to fill the data in PAIRS or	HASH in	$format, and
	   then	sends it to the	$fh (by	default	the selected file)

	     open my $fh, '>', $file;
	     printi $fh, ...

	     printi \*STDERR, ...

       printp( [$fh], $format, PAIRS|HASH )
	   Calls sprintp() to fill the data in PAIRS or	HASH in	$format, and
	   then	sends it to the	$fh (by	default	the selected file)

       sprinti($format,	PAIRS|HASH|OBJECT)
	   The $format refers to some string, maybe the	result of a

	   The PAIRS (which may	be passed as LIST, HASH, or blessed HASH)
	   contains a mixture of special and normal variables to be filled in.
	   The names of	the special variables (the options) start with an
	   underscore ("_").

	    -Option  --Default
	     _append   undef
	     _count    undef
	     _join     ', '
	     _prepend  undef

	   _append => STRING|OBJECT
	     Text as STRING appended after $format, without interpolation.

	   _count => INTEGER
	     Result of the translation process:	when Log::Report subroutine
	     __xn is are used for count-sensitive translation.	Those function
	     may add more specials to the parameter list.

	   _join => STRING
	     Which STRING to use when an ARRAY is being	filled-in as

	   _prepend => STRING|OBJECT
	     Text as STRING prepended before $format, without interpolation.
	     This may also be an OBJECT	which gets stringified,	but variables
	     not filled-in.

       sprintp($format,	LIST, PAIRS)
	   Where sprinti() uses	named parameters --especially useful when the
	   strings need	translation-- this function stays close	to the
	   standard "sprintf()".  All features of POSIX	formats	are supported.
	   This	should say enough: you can use "%3$0#5.*d", if you like.

	   It may be useful to know that the positional	$format	is rewritten
	   and then fed	into sprinti().	 Be careful with the length of the
	   LIST: superfluous parameter PAIRS are passed	along to "sprinti()",
	   and should only contain "specials": parameter names which start
	   with	'_'.

	   example: of the rewrite

	     # positional parameters
	     my	$x = sprintp "dumpfiles: %s\n",	\@dumpfiles
		, _join	=> ':';

	     # is rewritten into, and then processed as
	     my	$x = sprinti "dumpfiles: {_1}\n"
		, _1 =>	\@dumpfiles, _join => ':';

   Why use "printi()", not "printf()"?
       The "printf()" function is provided by Perl's CORE; you do not need to
       install any module to use it.  Why would	you use	consider using this

	   "printf()" uses positional parameters, where	printi() uses names to
	   refer to the	values to be filled-in.	 Especially in a set-up	with
	   translations, where the format strings get extracted	into PO-files,
	   it is much clearer to use names.  This is also a disadvantage of

       pluggable serializers
	   "printi()" supports serialization for specific data-types: how to
	   interpolate "undef",	HASHes,	etc.

       pluggable modifiers
	   Especially useful in	context	of translations, the FORMAT string may
	   contain (language specific) helpers to insert the values correctly.

       correct use of utf8
	   Sized string	formatting in "printf()" is broken: it takes your
	   string as bytes, not	Perl strings (which may	be utf8).  In unicode,
	   one "character" may use many	bytes.	Also, some characters are
	   displayed double wide, for instance in Chinese.  The	printi()
	   implementation will use Unicode::GCString for correct behavior.

       automatic output	encoding (for HTML)
	   You can globally declare that all produced strings must be encoded
	   in a	certain	format,	for instance that HTML entities	should be

   Four	components
       To fill-in a FORMAT, four clearly separated components play a role:

       1. modifiers
	   How to change the provided values, for instance to hide locale

       2. serializer
	   How to represent (the modified) the values correctly, for instance
	   "undef" and ARRAYs.

       3. conversion
	   The standard	UNIX format rules, like	%d.  One conversion rule has
	   been	added 'S', which provides unicode correct behavior.

       4. encoding
	   Prepare the output for a certain syntax, like HTML.


	 # sprinti() replaces "{$key$modifiers$conversion}" by

	 # sprintp() replaces "%pos{$modifiers}$conversion" by


	 #XXX Your manual-page reader may not support the unicode used
	 #XXX in the examples below.
	 printi	"price:	{price a~ %-10s}", price => $cost;
	 printi	"price:	{price a~ %-10s}", { price => $cost };
	 printp	"price:	%-10{a~}s", $cost;

	 $value	     = $cost (in a~)
	 $modifier   = convert a~ to local currency AL
	 $serializer = show float as string
	 $format     = column width %-10s
	 $encode     = AL into &pound;	   # when encodingFor('HTML')

   Interpolation: keys
       A key is	a bareword (like a variable name) or a list of barewords
       separated by dots (no blanks!)

       Please use explanatory key names, to help the translation process once
       you need	that (in the future).

       Simple keys

       A simple	key directly refers to a named parameter of the	function or

	 printi	"Username: {name}", name => 'John';

       You may also pass them as HASH or CODE:

	 printi	"Username: {name}", { name => 'John' };
	 printi	"Username: {name}", name => sub	{ 'John' };
	 printi	"Username: {name}", { name => sub { 'John' } };
	 printi	"Username: {name}", name => sub	{ sub {'John'} };

       The smartness of	pre-processing CODE is part of serialization.

       Complex keys

       [0.91] In the previous section, we kept our addressing it simple: let's
       change that now.	 Two alternatives for the same:

	 my $user = { name => 'John' };
	 printi	"Username: {name}", name => $user->{name}; # simple key
	 printi	"Username: {}", user => $user;	   # complex key

       The way these complex keys work,	is close to the	flexibility of
       template	toolkit: the only thing	you cannot do, is passing parameters
       to called CODE.

       You can pass a parameter	name as	HASH, which contains values.  This may
       even be nested into multiple levels.  You may also pass objects,	class
       (package	names),	and code references.

       In above	case of	"", when "user" is a HASH it will take	the
       value which belongs to the key "name".  When "user" is a	CODE, it will
       run code	to get a value.	 When "user" is	an object, the method "name"
       is called to get	a value	back.  When "user" is a	class name, the	"name"
       refers to an instance method on that class.

       More examples which do work:

	 # when	name is	a column in the	database query result
	 printi	"Username: {}", user => $sth->fetchrow_hashref;

	 # call	a sub which does the database query, returning a HASH
	 printi	"Username: {}", user => sub { $db->getUser('John') };

	 # using an instance method (object)
	 { package User;
	   sub new  { bless { myname =>	$_[1] }, $_[0] }
	   sub name { $_[0]->{myname} }
	 my $user = User->new('John');
	 printi	"Username: {}", user => $user;

	 # using a class method
	 sub User::count   { 42	}
	 printi	"Username: {user.count}", user => 'User';

	 # nesting, mixing
	 printi	"Complain to {product.factory.address}", product => $p;

	 # mixed, here CODE, HASH, and Object
	 printi	"Username: {}", document =>	sub {
	   return +{ author => User->new('John') }

       Limitation: you cannot pass arguments to	CODE calls.

   Interpolation: Serialization
       The 'interpolation' functions have named	VARIABLES to be	filled-in, but
       also additional OPTIONS.	 To distinguish	between	the OPTIONS and
       VARIABLES (both a list of key-value pairs), the keys of the OPTIONS
       start with an underscore	"_".  As result	of this, please	avoid the use
       of keys which start with	an underscore in variable names.  On the other
       hand, you are allowed to	interpolate OPTION values in your strings.

       There is	no way of checking beforehand whether you have provided	all
       values to be interpolated in the	translated string.  When you refer to
       value which is missing, it will be interpreted as "undef".

	   Simple scalar values	are interpolated "as is"

	   When	a value	is passed as CODE reference, that function will	get
	   called to return the	value to be filled in.	For interpolating, the
	   following rules apply:

	   Takes the value where the scalar reference points to.

	   All members will be interpolated with ",aL" between the elements.
	   Alternatively (maybe	nicer),	you can	pass an	interpolation
	   parameter via the "_join" OPTION.

	     printi "matching files: {files}", files =>	\@files, _join => ', '

	   By default, HASHes are interpolated with sorted keys,

	      $key => $value, $key2 => $value2,	...

	   There is no quoting on the keys or values (yet).  Usually, this
	   will	produce	an ugly	result anyway.

	   With	the "serialization" parameter, you can overrule	the
	   interpolation of above defaults, but	also add rules for your	own
	   objects.  By	default, objects get stringified.

	     serialization => [	$myclass => \&name_in_reverse ]

	     sub name_in_reverse($$$)
	     {	 my ($formatter, $object, $args) = @_;
		 # the $args are all parameters	to be filled-in
		 scalar	reverse	$object->name;

   Interpolation: Modifiers
       Modifiers are used to change the	value to be inserted, before the
       characters get interpolated in the line.	 This is a powerful
       simplification.	Let's discuss this with	an example.

       In traditional (gnu) gettext, you would write:

	 printf(gettext("approx	pi: %.6f\n"), PI);

       to get PI printed with six digits in the	fragment.  Locale::TextDomain
       has two ways to achieve that:

	 printf	__"approx pi: %.6f\n", PI;
	 print __x"approx pi: {approx}\n", approx => sprintf("%.6f", PI);

       The first does not respect the wish to be able to reorder the arguments
       during translation (although there are ways to work around that)	 The
       second version is quite long.  The string to be translated differs
       between the two examples.

       With "Log::Report", above syntaxes do work as well, but you can also

	 # with	optional translations
	 print __x"approx pi: {pi%.6f}\n", pi => PI;

       The base	for "__x()" is the printi() provided by	this module.
       Internally, it will call	"printi" to fill-in parameters:

	 printi	"approx	pi: {pi%.6f}\n", pi => PI;

       Another example:

	 printi	"{perms} {links%2d} {user%-8s} {size%10d} {fn}\n",
	    perms => '-rw-r--r--', links => 7, user => 'me',
	    size => 12345, fn => $filename;

       An additional advantage (when you use translation) is the fact that not
       all languages produce comparable	length strings.	 Now, the translators
       can change the format, such that	the layout of tables is	optimal	for
       their language.

       Above example in	printp() syntax, shorter but less maintainable:

	 printp	"%s %2d	%-8s 10d %s\n",
	    '-rw-r--r--', 7, 'me', 12345, $filename;

   Interpolation: default modifiers
       Default modifier: POSIX format

       As shown	in the examples	above, you can specify a format.  This can,
       for instance, help you with rounding or columns:

	 printp	"I = {pi%.3f}",	pi => 3.1415;
	 printp	"weight	is {kilogram%d}", kilogram => 127*OUNCE_PER_KILO;
	 printp	"{filename%-20.20s}\n",	filename => $fn;

       - improvements on POSIX format

       The POSIX "printf()" does not handle unicode strings.  Perl does
       understand that the 's' modifier	may need to insert utf8	so does	not
       count bytes but characters.  "printi()" does not	use characters but
       "grapheme clusters" via Unicode::GCString.  Now,	also composed
       characters do work correctly.

       Additionally, you can use the new 'S' conversion	to count in columns.
       In fixed-width fonts, graphemes can have	width 0, 1 or 2.  For
       instance, Chinese characters have width 2.  When	printing in fixed-
       width, this 'S' is probably the better choice over 's'.	When the field
       does not	specify	its width, then	there is no performance	penalty	for
       using 'S'.

	 # name	right aligned, commas on same position,	always
	 printp	"name: {name%20S},\n", name => $some_chinese;

       Default modifier: BYTES

       [0.91] Too often, you have to translate a (file)	size into humanly
       readible	format.	 The "BYTES" modifier simplifies this a	lot:

	 printp	"{size BYTES} {fn}\n", fn => $fn, size => -s $fn;

       The output will always be 6 characters.	Examples are "999  B", "1.2
       kB", and	" 27 MB".

       Default modifiers: YEAR,	DATE, TIME, DT,	and DT()

       [0.91] A	set of modifiers help displaying dates and times.  They	are a
       little flexible in values they accept, but do not expect	miracles: when
       it get harder, you will need to process it yourself.

       The actual treatment of a time value depends on the value: three
       different situations:

       1. numeric
	   A pure numeric value	is considered "seconds since epoch", unless it
	   is smaller than 21000000, in	which case it is taken as date without

       2. date format without time-zone
	   The same formats are	understood as in the next option, but without
	   time-zone information.  The date is processed as text as if in the
	   local time zone, and	the output in the local	time-zone.

       3. date format with time-zone
	   By far not all possible date	formats	are supported, just a few
	   common versions, like

	     2017-06-27	10:04:15 +02:00
	     2017-06-27	17:34:28.571491+02  # psql timestamp with zone
	     2017-06-27T10:04:15Z	    # iso 8601
	     20170627			    # only for YEAR and	DATE
	     2017-6-1			    # only for YEAR and	DATE
	     12:34			    # only for TIME

	   The meaning of 05-04-2017 is	unclear, so not	supported.
	   Milliseconds	get ignored.

	   When	the provided value has a timezone indication, it will get
	   converted into the local timezone of	the observer.

       The output of "YEAR" is in format 'YYYY', for "DATE" it will always be
       'YYYY-MM-DD', where "TIME" produces 'HH:mm:ss'.

       The short form "DT" is an alias for "DT(FT)".  The DT modifier can
       produce different formats:

	 DT(ASC)     : %a %b %e	%T %Y	    asctime output
	 DT(FT)	     : %F %T		    YYYY-MM-DD HH:mm:ss
	 DT(ISO)     : %FT%T%z		    iso8601
	 DT(RFC822)  : %a, %d %b %y %T %z   email old
	 DT(RFC2822) : %a, %d %b %Y %T %z   email newer

       You may suggest additional formats, or add your own modifier.

       Default modifiers: //word, //"string", //'string'

       [0.91] By default, an undefined value is	shown as text 'undef'.	Empty
       strings are shown as nothing.  This may not be nice.  You may want to
       be more specific	when a value is	missing.

	  "visitors: {count //0}"
	  "published: {date DT//'not yet'}"
	  "copyright: {year//2017 YEAR}

       Modifiers will usually return "undef" when they are called with an
       undefined or empty value.  By the right order of	'//', you may product
       different kinds of output:

	  "price: {price//5 EUR}"
	  "price: {price EUR//unknown}"

       Private modifiers

       You may pass your own modifiers.	 A modifier consists of	a selector and
       a CODE, which is	called when the	selector matches.  The selector	is
       either a	string or a regular expression.

	 # in Object Oriented syntax:
	 my $f = String::Print->new
	   ( modifiers => [ qr/[a~ax]/ => \&money ]

	 # in function syntax:
	 use String::Print 'printi', 'sprinti'
	   , modifiers => [ qr/[a~ax]/ => \&money ];

	 # the implementation:
	 sub money$$$$)
	 { my ($formatter, $modif, $value, $args) = @_;

	     $modif eq 'a~' ? sprintf("%.2f EUR", $value+0.0001)
	   : $modif eq 'ax' ? sprintf("%.2f GBP", $value/1.16+0.0001)
	   :		     'ERROR';

       Using printp() makes it a little	shorter, but will become quite complex
       when there are more parameter in	one string.

	 printi	"price:	{pa~}",	p => $pi;   # price: 3.14 EUR
	 printi	"price:	{pax}",	p => $pi;   # price: 2.71 GBP

	 printp	"price:	%{a~}s", $pi;	    # price: 3.14 EUR
	 printp	"price:	%{ax}s", $pi;	    # price: 2.71 GBP

       This is very useful in the translation context, where the translator
       can specify abstract formatting rules.  As example, see the (GNU)
       gettext files, in the translation table for Dutch into English.	The
       translator tells	us which currency to use in the	display.

	 msgid	"kostprijs: {pa~}"
	 msgstr	"price:	{pax}"

       Another example.	 Now, we want to add timestamps.  In this case,	we
       decide for modifier names in "\w", so we	need a blank to	separate the
       parameter from the modifer.

       Modifiers: stacking

       You can add more	than one modifier.  The	modifiers detect the extend of
       their own information (via a regular expression), and therefore the
       formatter understands where one ends and	the next begins.

       The modifiers are called	in order:

	 printi	"price:	{pa~%9s}\n", p => $p; #	price: aLaLaL123.45
	 printi	">{t T%10s}<", t => $now;    # >aLaL12:59:17<

	 printp	"price:	%9{a~}s\n", $p;	      #	price: aLaLaL123.45
	 printp	">%10{T}s<", $now;	     # >aLaL12:59:17<

   Output encoding
       [0.91] This module is also used by Log::Report::Template, which is used
       to insert (translated) strings with parameters into HTML	templates.
       You can imagine that some of the	parameter may need to be encoded to
       HTML in the template, and other not.

       example with Log::Report::Template

       In pure Template	Toolkit, you would write

	 # in your TT-template
	 <div>Username:	[% username | html %]</div>
	 # in your code
	 username => $user->name,

       With plain String::Print	with output encoding enabled, you can do:

	 # in your TT-template
	 <div>[% show_username %]</div>
	 # in your code	with encodeFor('HTML')
	 show_username => printi("Username: {user}", user => $user->name),
	 # or
	 show_username => printp("Username: %s", $user->name),

       That does not look very efficient, however it changes for the good when
       this is combined	with Log::Report::Lexicon (translations)  You can
       either do:

	 # in your TT-template
	 <div>[% show_username %]</div>
	 # in your code	with encodeFor('HTML')
	 show_username => __x("Username: {user}", user => $user->name),


	 # in your TT-template with encodeFor('HTML')
	 <div>[% loc("Username:	{user}", user => username) %]</div>
	 # in your code
	 username => $user->name,

       Even shorter:

	 # in your TT-template with encodeFor('HTML')
	 <div>[% loc("Username:	{}", user => userobj) %]</div>
	 # in your code
	 userobj => $user,


	 # in your TT-template with encodeFor('HTML')
	 <div>[% loc("Username:	{}") %]</div>
	 # in your code
	 user => $user,

       Shorter that the	original, and translations for free!  More examples in

       Output encoding exclusion

       In some cases, the data which is	inserted is already encoded in the
       output syntax.  For instance, you already have HTML to be included.

       The default exclusion rule for HTML output is "qr/html$/i", which means
       that all	inserted named parameters, where the name ends on "html" will
       not get html-entity encoded.

       This will work by default:

	 # with	encodeFor('HTML')
	 printp	"Me & Co: {name}, {description_html}",
	    name => 'RenA(C)', description_html	=> $descr;

       This may	result in:

	 Me &amp; Co: Ren&eacute;, <font color="red">new member</font>

       Better not to have HTML in your program:	leave it to the	template.  But
       in some cases, you have no choice.

   Compared to other modules on	CPAN
       There are a quite a number of modules on	CPAN which extend the
       functionality of	"printf()".  To	name a few: String::Format
       <>, String::Errf
       <http://>, String::Formatter
       Text::Sprintf::Named <
       Named>, Acme::StringFormat <
       StringFormat>, Text::sprintf <
       sprintfn>, Log::Sprintf <>, and
       String::Sprintf <>.	They
       are all slightly	different.

       When the	"String::Print"	module was created, none of the	modules
       mentioned above handled unicode correctly.  Global configuration	of
       serializers and modifiers is also usually not possible, sometimes
       provided	per explicit function call.  Only "String::Print" cleanly
       separates the roles of serializers, modifiers, and conversions.

       "String::Print" is nicely integrated with Log::Report.

       This module is part of String-Print distribution	version	0.91, built on
       June 27,	2017. Website:

       Copyrights 2016-2017 by [Mark Overmeer].	For other contributors see

       This program is free software; you can redistribute it and/or modify it
       under the Artistic license.  See

perl v5.24.1			  2017-06-27		      String::Print(3)


Want to link to this manual page? Use this URL:

home | help