Kirby Kirby - 1 month ago 12
Perl Question

Is it possible get a particular argument in printf format in perl in command line?

It's needed to build a string

foobar is not foo and not bar
.

In
printf
format
%$2s
, "2" means a particular argument position.

But it doesn't work in perl:

$ perl -e "printf('%$1s$2s is not %$1s and not %$2s', 'foo', 'bar');"
%2 is not %1 and not %2


My env:

$ perl --version

This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
(with 29 registered patches, see perl -V for more detail)

Answer

Your quoting is off.

perl -E 'say sprintf(q{%1$s%2$s is not %1$s and not %2$s}, "foo", "bar");'
foobar is not foo and not bar

You cannot use double quotes "" for the -e because your shell gets confused. You need single quotes there. But if you use double quotes for the printf pattern with the %1$s syntax, Perl will try to interpolate the $s, which doesn't work. So use a non-quoting q{} or escape the single quotes '' with \'. Or escape the $s.

If you turn on use strict and use warnings you'll see:

$ perl -E 'use strict; use warnings; say sprintf("%1$s%2$s is not %1$s and not %2$s", "foo", "bar");'
Global symbol "$s" requires explicit package name at -e line 1.
Global symbol "$s" requires explicit package name at -e line 1.
Global symbol "$s" requires explicit package name at -e line 1.
Global symbol "$s" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.

That's with single quotes '' for -e and double quotes "" for the pattern.

$ perl -E "use strict; use warnings; say sprintf('%1$s%2$s is not %1$s and not %2$s', 'foo', 'bar');"
Invalid conversion in sprintf: "%1 " at -e line 1.
Invalid conversion in sprintf: "%2" at -e line 1.
%2 is not %1 and not %2

Now the shell tried to interpolate $s because of the double quotes "". So Perl never sees it. It sees the pattern as "%1 %2 is not %1 and not %2", which it cannot understand. (Note that the % will not get interpolated in double quoted strings in Perl).