2016-11-07 7 views
1

文字列foobar is not foo and not barを作成する必要があります。コマンドラインでperlのprintf形式で特定の引数を取得することは可能ですか?

printfフォーマット%$2sでは、「2」は特定の引数位置を意味します。

しかし、それはperlで動作しません:

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

マイ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) 
+0

@HunterMcMillen、あなたは関数を作成するような意味ですか? '%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{}を使用するか、単一引用符''\'でエスケープしてください。または、$をエスケープします。

あなたはuse strictをオンにしuse warnings場合は、表示されます:単一引用符-eため''とパターンのための二重引用符""てい

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

$ 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 'はstrictを使います。警告を使う。 sprintf(\ '%1 $ s%2 $ sは%1 $ sではなく%2 $ s \'、\ 'foo \'、\ 'bar \'); ''です。エラー: 'bash:予期しないトークンの近くに構文エラーがあります') '' – Kirby

+1

@Kirbyそれは良い質問です。 '('と ')'を削除した場合(それらは必要ありません)、より多くの入力を期待し、プログラムを実行しません。私の頭の上から私はそれが好きではないか分からない。しかし、シェル引用やエスケープは難しいです。私の提案は、パターンのために 'q {}'を使い、あなたがargsのために好きなものを使うことです。私は 'printf q {%1 $ d ...}、qw(foo bar);'を実行するので、引用符を扱う必要はありません。 – simbabque

+0

ありがとう! – Kirby

2

これは、* nixの上で私の作品:

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");' 

(あなたがドル記号をエスケープする必要がないように私はPerlプログラム内q{}''からの切り替えを示唆しているだろうが、あなたがとにかく不足した\nのために二重引用符が必要です。)

関連する問題