2016-11-07 3 views
1

Необходимо построить строку foobar is not foo and not bar.Возможно ли получить конкретный аргумент в формате printf в perl в командной строке?

В printf формате %$2s, "2" означает конкретную позицию аргумента.

Но он не работает в Perl:

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

Мой окр:

$ 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) 
+0

@ HunterMcMillen, вы имеете в виду, как создать функцию? 'perl -e 'sub ppp() {printf ('% 1 $ s% 2 $ s не% 1 $ s, а не% 2 $ s ',' foo ',' bar ');} ppp();" 'как это? .. Это не работает. – Kirby

ответ

6

Ваше цитирование отключено.

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 

Вы не можете использовать двойные кавычки "" для -e, потому что ваша оболочка запутается. Вам нужны одинарные кавычки. Но если вы используете двойные кавычки для шаблона printf с синтаксисом %1$s, Perl попытается интерполировать $s, который не работает. Поэтому используйте неотображающий q{} или избегайте одиночных котировок '' с \'. Или уберите $ s.

Если вы включите use strict и use warnings вы увидите:

$ 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. 

Это одинарные кавычки '' для -e и двойные кавычки "" для шаблона.

$ 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 

Теперь оболочка пыталась интерполировать $s из-за двойных кавычек "". Поэтому Perl никогда не видит этого. Он видит шаблон как "%1 %2 is not %1 and not %2", который он не может понять. (Обратите внимание, что % не будет интерполировать в двойных кавычках в Perl).

+0

Я получил этот момент, спасибо!Что-то неясно, если я использую одинарные кавычки, почему это приводит к ошибке: 'perl -E 'use strict; использовать предупреждения; скажем, sprintf (\ '% 1 $ s% 2 $ s не% 1 $ s, а не% 2 $ s \', \ 'foo \', \ 'bar \'); '. error: 'bash: синтаксическая ошибка около неожиданного токена ')'' – Kirby

+1

@ Кирби, это хороший вопрос. Если вы удалите скобки '(' и ')' (они вам не нужны), она просто ожидает большего ввода и не запускает вашу программу. С головы до ног я не знаю, что ему не нравится. Но кавычки и экранирование оболочки сложны. Мое предложение - использовать 'q {}' для шаблона и все, что вам нравится для args. Я бы сделал 'printf q {% 1 $ d ...}, qw (foo bar);' поэтому мне не нужно иметь дело с котировками вообще – simbabque

+0

получил его, спасибо! – Kirby

2

Это работает для меня на * Никс:

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

ВИДЕТЬ sprintf documentation, в в частности примеры в самом конце:

Here are some more examples; be aware that when using an explicit index, the $ may need escaping:

printf "%2\$d %d\n",  12, 34;  # will print "34 12\n" 
printf "%2\$d %d %d\n", 12, 34;  # will print "34 12 34\n" 
printf "%3\$d %d %d\n", 12, 34, 56; # will print "56 12 34\n" 
printf "%2\$*3\$d %d\n", 12, 34, 3; # will print " 34 12\n" 
printf "%*1\$.*f\n",  4, 5, 10; # will print "5.0000\n" 
1

Давайте посмотрим на программы, который вы передаете perl:

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

Как вы можете видеть, нет никакого $1 или $2 в вашей программе, потому что вы неправильно построили вашу команду оболочки. Точно так же, как Perl интерполирует в двойных кавычках, так же делают sh и связанные с ними оболочки. Вы должны использовать одинарные кавычки!

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

(я бы предложил переход от '' к q{} внутри программы на Perl, так что вы не должны бежать знаки доллара, но вам нужно двойные кавычки для \n вы пропали без вести в любом случае.)