yn2011's blog

技術メモ

bashの`printf "%.s" hoge`と`printf "%0s" hoge`の違い

環境

事象

$ printf "%0s" hoge
hoge

$ printf "%.s" hoge
# 何も表示されない

疑問

  • 文字列かつ精度指定は文字数の制限なので0を指定したら何も表示されないのでは
    • "%.s"で何も表示されないのはピリオド=精度0と解釈されているからだと思う

オプションである精度は、ピリオド ('.') とそれに続く10進数という 形式で指定する (10進数はオプション) 。 10進数の文字列の代わりに "" や "m$" (m は 10 進整数)を書くこともできる。 "" と "m$" はそれぞれ、次の引き数と m 番目の引き数を精度として 使うことを指定する (これらの引き数は int 型でなければならない)。 精度として '.' だけが指定された場合、 精度はゼロとみなされる。 精度が負の数だった場合、 精度は指定されなかったものとみなされる。 d, i, o, u, x, X 変換では、表示される最小の桁数を指定する。 a, A, e, E, f, F 変換では、小数点以下に表示される数字の桁数を指定する。 g と G 変換では、有効数字の最大桁数を指定する。 s と S 変換では、文字列から出力される最大文字数を指定する。

Man page of PRINTFより引用

解決

  • 文字列の場合は%5.3sは全体5桁、最大3桁の文字列を出力する
$ printf "%5.3s" 123456
  123 # 全体の長さが5なので半角空白が2つ入る
  • したがって、%.s%0.0sと解釈されて最大0桁の文字列出力だから何も表示されなかった(推測)*1
$ printf "%0.0s" hoge
# 何も表示されない
  • ちなみに、%0sで表示されたのは最大桁の指定無しだったから(推測)
    • 全体の文字数<引数の文字数の場合は全て表示
$ printf "%1s" hoge
hoge

精度は変換指定子によって意味が異なる

  • 何となく%fで小数点以下を指定するイメージしかなかった
  • ちゃんと確認しよう

これがしたかった

  • そもそもなんで気になっていたかというと、このスクリプトの原理が分からなかったからでした
$ printf hoge\\n"%.s" {1..5}
hoge
hoge
hoge
hoge
hoge

参考

*1:実装は確認していないので