2013-03-22 15 views
7

私は、bashに新しい行シンボルを含む変数を表示するのとちょっと混乱しています。bash printf with new line

var="Age:\n20\ncolor:\nred" 
echo -e $var 
Age: 
20 
color: 
red 

これは働いているが、多くの人々は、オプションでエコーするnot portableit is better to use printfであると言います。

私はprinfを一度も使用しませんでした。 echoコマンドを発行するマニュアルに従って:

printf '%s\n' "$var" 
Age:\n20\ncoloe:\nred 

しかし、変数内で\ nを解析しません。

printf "Surname: %s\nName: %s\n" "$SURNAME" "$LASTNAME" 

しかし、それは使用すること慣れていない私の場合ではありませんし、私の視点から:マニュアルは通常、この例を持っています。

のprintf "$するvar \ n" は

それは移植性がある:私は単に私がこれを使用することができることを次のように入力して分かりましたか? $ varをメールコマンドに渡すと、新しい改行が保存されますか?

printf "$var\n" | mail -s subj [email protected] 
+0

printf' 'の問題は、組み込みの一部のシェル(bashのとは、ksh93)上にシェルが、他の外部プロセス(SH、ksh88では、CSH)であることです。古いシェルで 'printf'を使うと、何回使ったかによってプログラムが遅くなる可能性があります。 – cdarke

答えて

16

printf%b書式指定子は、特にecho -eを置き換えるためのものだった(実際には、デフォルトでは、引数の特殊な解釈を求めechoにXSIの拡張機能。-eが指定されなかったとPOSIXによって許可されていません。)、 $'...'との相違点やフォーマット文字列の引数をprintfに変更するなど、事実上あらゆる点で同じです。

$ (var='Age:\n20\ncolor:\nred'; printf '%b\n' "$var") 
Age: 
20 
color: 
red 

あなたは、一般的にあなたのプログラムが正確な値を制御し、具体的にフォーマット文字列であることを意図されていない限り、フォーマット文字列に変数を拡大することは避けてください。あなたの最後の例は、printf-vオプションのために、Bashで非常に危険な可能性があります。

# Bad! 
var='-v_[$(echo "oops, arbitrary code execution" >&2)0]' 
printf "$var" foo 

通常、あなたが特別な移植性の要件がない限り%bを避けることをお勧めします。リテラルデータの代わりにエスケープコードを変数に格納すると、コードとデータの分離の原則に違反します。これは問題ありませんが、通常は、$'...'の引用符を使用して値を代入する方が良いでしょう。これはPOSIXの次のバージョンで指定されていて、Bashとほとんどのkshフレーバで利用できます。

x=$'foo\nbar'; printf '%s\n' "$x" # Good 
x=(foo bar); printf '%s\n' "${x[@]}" # Also good (depending on the goal) 
x='foo\nbar'; printf '%b\n' "$x"  # Ok, especially for compatibility 
x='foo\nbar'; printf -- "$x"   # Avoid if possible, without specific reason 
+0

詳細な回答ありがとうございます。 – idobr

+0

@ormaaj:誰か(あなた?)がPOSIXの次のバージョンに追加される予定の機能を紹介しました。これについて公開されている草案がありますか?ちょっと興味があるんだけど。 – chepner

+0

@chepner仕様書のドラフトは、サブスクライバの一覧表示に使用できます。 2008年のTC1は既に完成しているので、今はいつでも外出するべきですが、[this](http://austingroupbugs.net/view.php?id=249)(そして他の "機能"の変更)は少なくとも誰かが[gmane](http://dir.gmane)のリストアーカイブを読むことができます。org/gmane.comp.standards.posix.austin.general)、またはバグトラッカーを検索してください。理論的には、適切なツールがあれば、バグトラッカーのdiffs(私はこれを試みていない)から現在の状態を構築することができます。 – ormaaj