geofflh has asked for the wisdom of the Perl Monks concerning the following question:

In my Perl reference manual, it describes a method of generating a variable field for output as -

 $w = 3; $str = "abc";  $line = sprint ("%${w}s ", $str);

This works just fine unless there is a " use strict; " in force. Other than putting a "no strict; code line; strict;" wrapper around the construct, how can I generate a variable output field within a strict setting?

Replies are listed 'Best First'.
Re: use of strict
by Athanasius (Archbishop) on Jul 25, 2017 at 07:40 UTC

    Hello geofflh, and welcome to the Monastery!

    Here’s another syntax variation you may find useful: including * in the format string of a call to printf (or sprintf):

    use strict; use warnings; my $w = 7; my $str = "abc"; printf ">%*s<\n", $w, $str;

    Output:

    17:34 >perl 1790_SoPW.pl > abc< 17:34 >

    — the * is replaced by the contents of the next variable in the following list, in this case $w, so the statement is equivalent to printf ">%7s<\n, $str.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: use of strict
by shmem (Chancellor) on Jul 25, 2017 at 07:28 UTC

    Use my:

    my ($w, $str, $line); $w = 3; $str = "abc"; $line = sprintf ("%${w}s ", $str);
    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: use of strict
by haukex (Archbishop) on Jul 25, 2017 at 07:41 UTC

    You've already got answers to your questions, I just wanted to add: For some more info on strict see also Use strict and warnings. And, in this case, you can parameterize the width of a sprintf format without interpolating into the format string:

    my $w = 5; my $str = "abc"; my $line = sprintf "%*s", $w, $str; print "<", $line, ">\n"; __END__ < abc>

    Update: Athanasius beat me to it ;-)

Re: use of strict
by Corion (Patriarch) on Jul 25, 2017 at 07:31 UTC

    What is the error message that you get when you use strict?

    There is no sprint function in Perl, but there is a sprintf function in Perl.

    The common approach is to predeclare your variables as lexical variables using the my keyword.

    my $w = 3; my $str = "abc"; my $line = sprintf "%${w}s ", $str; # still has an error

    Not knowing the error you got, after declaring your variable names, you will still get an error that you can't use 3 as a reference while strict is in effect. This is because Perl sees %${w} and interprets it as %{ ${ w }}, trying to interpret the value of $w as a reference. You can circumvent that problem by building your format string piecemeal:

    my $line = sprintf "%" . $w . "s ", $str;
      you will still get an error that you can't use 3 as a reference while strict is in effect. This is because Perl sees %${w} and interprets it as %{ ${ w }}, trying to interpret the value of $w as a reference.

      Did you test your assumption?

      my $w = 5; my $str = "abc"; my $line = sprintf "%${w}s ", $str; print "'$line'\n"; __END__ ' abc '

      The format string is %5s with perl 5, version 20, subversion 2 (v5.20.2).

      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

        No, I didn't test my assumption, but my wonderment about it slowly ceases.

        Perl does not interpolate hashes in strings, as it accurately says in perlop:

        For constructs that do interpolate, variables beginning with "$" or "@" are interpolated.
        use strict; print "%foo";

        So, my argumentation above is simply wrong as Perl will not go looking for a hash (reference).