printfでのパディング
シェルでprintf
というコマンドを使うとecho
ではできないフォーマットを指定したりすることも出来ます。
その中で、フォーマットの中で%d
が数字、%s
が文字を表していて後ろから引数として渡してそこに埋められます。
1 2 |
|
これらのs
とかd
とかの記号の前に数字を入れるとそれの幅だけを予約し、空いた分は空白として出力します。
1 2 |
|
マイナスを入れると後ろを空ける。
1 2 |
|
予約した分よりも入力の文字が多い場合にはその文字列分だけ場所をとります。
1 2 |
|
この辺の空白埋めは%d
でも同じです。
GNU/BSDでも少なくともここに書いてあることは同じようになります。
printfでの整数のゼロパディング
%d
に対して、パディング記法で数字の前に0
を置くと0で埋めることができます。
1 2 |
|
もし、数字がマイナスの場合、マイナスはゼロの左側に出ます。
1 2 |
|
マイナスの分も1つ文字を消化した上で。
この0
は.
に変えても同じようにゼロ埋めになります。
一方、記法の方で0
の前にマイナスを付けると
単に右側の空白埋めになります。
1 2 |
|
ここは単なる空白の場合と異なりますが、ここでは5
の前の0
と-
のオプションが
重複して、-
の方が優先された、という状態です。
数字のゼロ埋めなので右に埋めると数字が根本的に変わるのでそのようなことは出来ないようになっているようです。
オプションの重複、という意味では、 実際、これを逆にしても
1 2 |
|
同じ出力。
また、0
の代わりに.
を書いてもゼロ埋めになります。
1 2 |
|
これは.<N>
が精度を表す記法で、
5桁の精度ということなのですが、
整数の場合には単にその桁分の左ゼロ埋めで表記されます。
入力桁数の方が大きい場合には単にそのまま出力されます。
少数の%f
を使うと、
1 2 3 4 |
|
こんな感じで小数点以下が5桁になるようにされているのがわかります。
下の方は最後の桁はその下の桁を四捨五入して繰り上げで8
から9
に変換されています。
なのでこちらはパディングとは違うものですが、 整数に対して行うとゼロパディングと同じようになっているだけです。
右梅にしようとして-
を前につけても精度の方が優先されて変わりません。
1 2 |
|
ただし、.
より後ろにつけると、ここでもGNU/BSDで違っていて
GNU:
1 2 |
|
BSD:
1 2 |
|
のような感じで、BSDは単に精度もパディングも無視されたような状態で、
一方でGNUの方は%
記法が無視され、かつ-5
の部分が0-5l
に変換されています。
(多分何かしら考えれば分かりそうですがパッと考えどうしてこうなるか良くわからない。)
いずれにしろこの辺は通常用途では無いと思うのでおいておきます。
printfでの文字列のゼロパディング
今回の本題、%s
に対してのゼロパディング。
そもそもゼロで埋めるのは数字だから左埋めしても意味がわかるものの、 通常の文字だと意味がよくわからなくなることもあるかとは思います。
そんなわけでこれも通常用途とはあまり言えないかもしれませんが、
プログラムの中では空白では無く何かしらの文字で埋きたい場合や、
何かしら別の文字列で埋める場合に一旦0
にして置換したほうが
空白よりもやりやすいこともあるかも。
ということでやってみると、
GNU:
1 2 |
|
BSD:
1 2 |
|
ということで、GNUの場合はゼロではなく空白埋めになり、一方BSDでは文字列に対してでもゼロ埋めになります。
これどんな用途で使いたかったかというと、
文字幅が可変なものに対してその上下に文字列と同じ長さだけの#
とか書いてバナー的にしたい時、
1 2 3 4 5 |
|
こんなことをやってました。
ゼロ埋めした上で何も渡さないのでn
の分だけ0
が表示されるつもり。
それをtr
で#
に変換して
1 2 3 |
|
こんな出力にしたかった。
で、macOSでやってみたところうまくいってOKと思っていたら うまく行ったのでこれでOKかと思いきやGNUなLinux環境でやってみると
1 2 3 |
|
みたいな感じで空行になってました。
これは上で見たように%05s
とか文字列に対してゼロ埋めしようとしても
GNU版printf
だと空白埋めにしてしまうから。
これに対しては
1 2 3 4 5 |
|
のようにd
を使ってやればGNUでもBSDでもバナー表示になります。
Ref
GNU版のマニュアル:
man printf
はエスケープシーケンスについての記述が少しありますが、
%d
や%s
に関してはあまりなし。
man
中にリンクのある上のマニュアルページにもパディングについてはなし。
man 3 printf
を見ると、
1 2 3 4 |
|
とあり、d
とかにはゼロ埋めします、と書いてありますが、s
は含まれていません。
BSD版のマニュアル:
上のはFreeBSDのprintf
のマニュアルですが、macOSのman printf
のものも上と同じJuly 1, 2020
でmacOS 13.3のものとそこだけ違いますがあとは多分一緒。
ここには
1 2 3 |
|
と、どのタイプに対して、ということは書いておらず、単にゼロ埋めします、と書いてあります。
また、-
と同時に使われた場合には0
よりも優先して使われる、ともあります。
man 3 printf
はFreeBSDの最新版だと2018年版になってましたが、macOSだと2009年で、おそらく
以下のものと同じ
ここ見ると
1 2 3 4 5 |
|
となっていて、こちらも0
が付けばどれでもゼロ埋めする、とあります。
加えてここでは.
の精度をつけられるタイプでそのflagが付いてる場合にはゼロパディングのフラグは無視される、とあります。
文字列の場合にはそのままゼロパディングされます。
というわけで、マニュアルをちゃんと読むと書いてありました、と。