PowerShell フォーマットに関すること(-fを使ったフォーマット指定)
1.はじめに
フォーマット変換はどの言語にもある機能だと思うが、すこしクセがあるという印象を持っている。PowerShellにおけるフォーマット変換はどんなものだろうかと思い実験してみた。切り口を簡便にするためC言語のフォーマット指定子(printfなどで使う書式指定)を念頭に置きながら使い方を学んでいこうと思う。
2.環境
PowerShellのバージョンは以下の通り。
PS > $PSVersionTable Name Value ---- ----- PSVersion 5.1.18362.752 ・・・以下、略・・・
3.目指すところ
- -fを使用したフォーマット指定を学ぶ
- C言語のprintfのフォーマット指定を念頭に確認する
※Format-Tableなどの出力整形コマンドレットは扱わない
4.やってみよう
先にも書いたが、話を単純にするために-f
を使ったフォーマット指定方式で統一する。[String]::Format
やToString
によるフォーマット指定などは扱わない。
4.1 -fを使用したフォーマット指定の基本
まずは基本形として、printf("%d", 10)
を-fで実現してみる。
PS > "{0}" -f 10 10
{0}
が置換される部分、-fの後ろにあるデータ(例では10という値)で{0}
を置換する感じになる。
PS > "{0}---{0}" -f 10 10---10
{0}
は単純に-fの後ろにあるデータの何番目で置き換えるかをインデックスで指定しているだけなので(0開始)、上記のようにフォーマット部分に同じインデックスのものを複数置いてもOK。
PS > $a = 10 PS > $b = 100 PS > "{0}---{1}" -f $a, $b 10---100
{0}``{1}
と異なるインデックスのものを並べてもOK。その時には、-fの後ろに対応する分のデータを置いてあげればよい。{0}
は$aの値で置換され、{1}
は$bの値で置換される。
4.2 配列を使った例
ふと気になったので、配列を-fで指定してみた。
PS > $a = @(10, 20) PS > $a 10 20 PS > echo ("{0}---{1}" -f $a) 10---20
配列は-fの後ろで一つ一つ書かなくても、自動的にa[0],a[1]
と展開して解釈してくれるようだ。
ではハッシュテーブルならどうだろう?
PS > $b Name Value ---- ----- lemon 80 apple 100 banana 50 PS > "{apple}" -f $b 文字列 入力文字列の形式が正しくありません。 の書式設定のエラーです。 発生場所 行:1 文字:1 + "{apple}" -f $b + ~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: ({apple}:String) []、RuntimeException + FullyQualifiedErrorId : FormatError
{0}
の0がただのインデックスなら、ハッシュテーブルのキーを書けば対応するバリューで置き換えてくれるかなぁ~と思い、"{apple}" -f $b
としてみたができないようだ。ご存じの方いたら教えてください。
PS > "{0}" -f $b["apple"] 100
ハッシュテーブルの場合は、上記のように愚直に-fで指定してあげる必要があるようだ(printfの本来の使い方と同じ)。
4.3 出力フォーマット指定
printfでは、"%d"(整数)、"%f"(小数)、"%s"(文字列)などで出力形式を指定する。PowerShellでは変数の型はあまり気にしたことがないが、敢えて型を指定したうえでフォーマット指定ができるか確認してみた。
PS > [byte]$a = 255 ・・・Byte型 PS > [bool]$b = 1 -eq 1 ・・・Boolean型 PS > [float]$c = 1.2345 ・・・float型(小数) PS > [double]$d = 1.234578901 ・・・deouble型(小数) PS > [string]$e = "abcde" ・・・string型(文字列) PS > [int]$f = 100 ・・・int型(整数) PS > [long]$g = 1234567890 ・・・long型(整数) PS > "{0},{1},{2},{3},{4},{5},{6}" -f $a, $b, $c, $d, $e, $f, $g 255,True,1.2345,1.234578901,abcde,100,1234567890
想像通り、特に型に関しては気にすることがなさそう。単純に-fで指定されたデータを表示するだけのようだ。
PS > [datetime]$h = "2020/01/01 00:00:00" PS > "{0}" -f $h 2020/01/01 0:00:00
忘れていたので追加確認。日付型も特に問題なし。(日付フォーマット指定については後述)
4.4 基数変換
printfでは%x
(16進)、%d
(10進)で基数変換ができた。PowerShellではどうなるか確認してみる。(差し当たり使いそうなHEX->DEC、DEC->HEXのみ調査)。
PS > "HEX {0:x}" -f 100 HEX 64 PS > "DEC {0:d}" -f 0x64 DEC 100
{n:r}
nが-fの後ろにあるデータの何番目で置き換えるかを指定するインデックス、rが基数の指定。
・参照 https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-numeric-format-strings
4.5 表示桁数の指定
printfは"%10d"のように書くと表示桁を10桁とするようにできた。PowerShellではどうなるか確認してみた。(分かりやすいように両端を><で括る)
PS > ">{0}<" -f 100 ・・・桁指定なし >100< PS > ">{0,10}<" -f 100 ・・・10桁指定で表示 > 100<
{n,f}
nが-fの後ろにあるデータの何番目で置き換えるかを指定するインデックス、fが桁数の指定。
整数型データでの検証。printf("%10d",10)と同等のことができた。
PS > ">{0}<" -f "abc" >abc< PS > ">{0,10}<" -f "abc" > abc<
文字列型データでの検証。printf("%10s","abc")と同等のことができた。
4.6 右詰・左詰の指定
PS > ">{0,10}<" -f 100 ・・・右詰め指定 > 100< PS > ">{0,-10}<" -f 100 ・・・左詰め指定 >100 <
{n,f}
nが-fの後ろにあるデータの何番目で置き換えるかを指定するインデックス、fが桁数の指定。fをマイナス値にすると「左詰め」にできる。この辺はprintfの書式指定と同じなのでなじみやすい。
PS > ">{0,10}<" -f "abc" ・・・右詰め指定 > abc< PS > ">{0,-10}<" -f "abc" ・・・左詰め指定 >abc <
文字列型データでも同じ。
4.7 数字の桁数(0埋め有り/無し)
printfでは"%010d"などとすると、0埋め有り(0パディング)の10桁と指定することができた。PowerShellではどうなるか確認してみた。なお、#についても併せて確認する。
- 0:1文字の数字(0埋め有り)
:1文字の数字(0埋め無し)
PS > "{0:#}" -f 0 ・・・#指定では0はデータ無しの扱いなので、0と表示されない PS > "{0:0}" -f 0 ・・・0指定では0も0埋めされるので結果的に0が表示される 0
上記のように#を使ったときは、0の扱いには注意。
PS > "{0:##}" -f 5 ・・・2桁指定(0埋め無し) 5 PS > "{0:00}" -f 5 ・・・2桁指定(0埋め有り) 05 PS > "{0:0#}" -f 5 ・・・2桁指定(10の位0埋め有り) 05
一番上の例で分かる通り、#は該当する桁(10の位)に数字がない場合0埋めしない(スペースも無し)。一方で、二番目の例で分かる通り、0は該当する桁に数字がない場合0埋めする。
PS > "{0:0##}" -f 5 005
上記のように10の位、100の位がないデータで、10の位が#指定でも上位の100の位が0指定有ならば、いい感じに理解してくれるようだ(最上位に0があれば途中は何であれ0埋めしてくれる)。
4.8 小数、金額、パーセント(%)
(1)小数
小数の桁指定がどうなるかを確認してみた。
PS > "{0:#}" -f 5.25 ・・・整数部分の指定 5 PS > "{0:#.#}" -f 5.25 ・・・小数部分の指定を追加(小数1桁までの指定なので、小数2桁目で四捨五入される) 5.3 PS > "{0:#.##}" -f 5.25 ・・・小数部分の指定を追加(小数2桁までの指定) 5.25 PS > "{0:#.###}" -f 5.25 ・・・小数部分の指定を追加(小数3桁までの指定#) 5.25 PS > "{0:#.##0}" -f 5.25 ・・・小数部分の指定を追加(小数3桁までの指定0) 5.250
上記のように、ピリオド(.)を付けた左側が整数部、右側が小数部の桁指定となる。#と0の指定方法は、前述の内容と変わらないが、桁指定が足らない場合は四捨五入されてしまうことに注意する必要がある。また、最下位桁に0指定があれば、途中がなんであれ0埋めしてくれる。
(2)金額
金額も表示上3桁でカンマ(,)をつける場合が多い。
PS > "{0:#,###}" -f 100 100 PS > "{0:#,###}" -f 1000 1,000 PS > "{0:#,###}" -f 10000 10,000 PS > "{0:#,###}" -f 1000000 1,000,000 PS > "{0:#,###}" -f 1000000000 1,000,000,000 PS > "{0:#,###}" -f 1000000000000 1,000,000,000,000
とりあえず"{0:#,###}"
という指定をしておけば、いい感じに3桁ごとにカンマを入れてくれるようだ。
(3)%パーセント
0.25が25%だが、%をフォーマット指定に使うと0.25を25%にしてくれるようだ。
PS > "{0:#%}" -f 0.25 25% PS > "{0:#%}" -f 0.255 26% PS > "{0:#.0%}" -f 0.255 25.5%
2番目の例をみると、小数3桁の表示指定がされていないと例のごとく四捨五入される。
4.9 符号の指定
正の数字の時には+を、負の数字の時には-を付ける方法について確認してみた。
PS > "{0:+#.##0;-#.##0}" -f 100.25 +100.250 PS > "{0:+#.##0;-#.##0}" -f -100.25 -100.250
{n:正の場合のフォーマット;負の場合のフォーマット}
nが-fの後ろにあるデータの何番目で置き換えるかを指定するインデックス、その後ろにセミコロン(;)で区切って、正の場合、負の場合のそれぞれのフォーマットを指定する。
マイクロソフトの説明によると、セミコロン(;)はセクションと呼ばれるものらしく、本来は正の場合、負の場合、零の場合の3パターンを指定することができるようだ。(先の例では、このうちの正、負の2パターンを指定しただけに過ぎない。)
PS > "{0:A;B;C}" -f 1 ・・・正の場合 A PS > "{0:A;B;C}" -f -1 ・・・負の場合 B PS > "{0:A;B;C}" -f 0 ・・・0の場合 C
上記の例を見れば、セクションの使い方が分かるはず。
PS > "{0:+0.00;-0.00;+-0.00}" -f 1 ・・・正の場合 +1.00 PS > "{0:+0.00;-0.00;+-0.00}" -f -1 ・・・負の場合 -1.00 PS > "{0:+0.00;-0.00;+-0.00}" -f 0 ・・・0の場合 +-0.00
具体的には、上記のような使い方をするか。
・参照 https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/custom-numeric-format-strings
4.10 日時のフォーマット
簡単なログ出力やファイル名に使うなど、現在時刻を取得して指定したフォーマットで使う場合は多い。日時のフォーマットはSQLはじめ様々な言語で指定できる。PowerShellではどうなのか確認してみた。
PS > "{0}" -f (Get-Date) ・・・単純出力 2020/06/13 15:12:20 PS > "{0:yyyyMMdd}" -f (Get-Date) ・・・年月日(0埋め有り)だけ 20200613 PS > "{0:yyyy-MM-dd}" -f (Get-Date) ・・・年月日にハイフンを入れてみた 2020-06-13 PS > "{0:yyyy-MM-dd ddd}" -f (Get-Date) ・・・曜日を入れてみた 2020-06-13 土 PS > "{0:yyyy-MM-dd dddd}" -f (Get-Date) ・・・長い曜日を入れてみた 2020-06-13 土曜日 PS > "{0:yyyy-MM-dd HH:mm:ss fff}" -f (Get-Date) ・・・時刻、ミリ秒まで入れてみた 2020-06-13 15:19:21 077
特に他言語と変わることなく普通に使えるようだ。
・参照 https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings
終.獲得した知識
- -fを使用したフォーマット指定の方法