［PowerShell / Python］フォーマット文字列ざっくりまとめ

C/Perlとかの`printf()`と比べると、PowerShellとPythonのフォーマット文字列が独特すぎてなかなかなじまないので、ざっくりと主要なものをまとめてみた

# pritnf()

標準ライブラリでおなじみのフォーマット文字列。
[Man page of PRINTF](https://linuxjm.osdn.jp/html/LDP_man-pages/man3/printf.3.html)

## 文字列

```perl
printf "\"%8s\"\n", "hello";  # 右寄せ8桁
printf "\"%-8s\"\n", "hello"; # 左寄せ8桁
```

出力

```text
"   hello"
"hello   "
```

## 数値

```perl
# 数値
$val = -1;
printf "%d\n", $val;    # val
printf "%u\n", $val;    # unsigned val
printf "%X\n", $val;    # HEX
printf "%x\n", $val;    # hex
printf "%4d\n", $val;   # 右寄せ4桁
printf "%04d\n", $val;  # 0埋め4桁
printf "%f\n", $val;    # float
printf "%8.3f\n", $val; # 全8桁・小数以下3桁
```

出力

```text
-1
18446744073709551615
FFFFFFFFFFFFFFFF
ffffffffffffffff
  -1
-001
-1.000000
  -1.000
```

# PowerShell

## 基本

指定の位置に`{n}`(nは引数の順序)を記述する。番号は必須

```powershell
$name = "くれりん"
Write-Output("こんにちは、{0}さん。" -f $name)
$hello = "こんにちわ"
Write-Output("{1}、{0}さん。" -f $name, $hello)
```

出力

```text
こんにちは、くれりんさん。
こんにちわ、くれりんさん。
```

## 文字列

```powershell
$str1 = "hello"
$str2 = "world"
Write-Output("'{0,8}'" -f $str1)  # 右寄せ
Write-Output("'{0,-8}'" -f $str1) # 左寄せ
```

出力

```text
'   hello'
'hello   '
```

## 数値

```powershell
$val = 254
Write-Output("{0}" -f $val)
Write-Output("{0,8}" -f $val)         # 8桁右寄せ
Write-Output("{0:00000000}" -f $val)  # 8桁0埋め
Write-Output("{0:d8}" -f $val)        # 8桁0埋め
```

出力

```text
254
     254
00000254
00000254
```

### 小数

```powershell
$val = 21.2345678
Write-Output("{0:.0000}" -f $val)     # 小数4桁
Write-Output("{0:f4}" -f $val)        # 小数4桁
Write-Output("{0:0000.000}" -f $val)  # 整数4桁小数3桁
```

出力

```text
21.2346
21.2346
0021.235
```

※こんな感じ(↓)に、書式指定子を使った整数部と小数部の両方の桁指定はできなさそう？

```powershell
Write-Output("{0:f4.3}" -f $val)
```

### 基数変換

```powershell
Write-Output("{0:x4}" -f $val)        # hex
Write-Output("{0:X4}" -f $val)        # HEX
```

出力

```text
00fe
00FE
```

### 桁区切り

カンマで3桁区切り以外にも、ハイフン付き電話番号のような特定の書式を設定するにはとても簡単にできる。

```powershell
$val = 16777216
Write-Output("{0:#,#}" -f $val)  # 3桁,区切り

$num = 09012345678
Write-Output("{0:000-0000-0000}" -f $num)
Write-Output("{0:###-####-####}" -f $num)
```

出力 (`0`でなく`#`を使うと0埋めされない)

```text
16,777,216
090-1234-5678
90-1234-5678
```

---

- 参考
    - [文字列の書式設定 - クラスライブラリ | ++C++; // 未確認飛行 C](https://ufcpp.net/study/dotnet/bcl_format.html)
    - [標準の数値書式指定文字列 | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-numeric-format-strings)
    - [カスタム数値書式指定文字列 | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/custom-numeric-format-strings)

# Python

`str.format()`を使用する。
とくに指定がない限りPython2/Python3共通。

## 基本

指定の位置に`{n}`(nは引数の順序)を記述する。PowerShellと異なり番号は省略すると引数の順序とみなされる。

```python
name = "くれりん"
print("こんにちわ、{}さん。".format(name))
hello = "こんにちわ"
print("{}、{}さん。".format(hello, name))
print("{1}、{0}さん。".format(name, hello))
```

出力

```text
こんにちわ、くれりんさん。
こんにちわ、くれりんさん。
こんにちわ、くれりんさん。
```

## 文字列

```python
str = "hello"
print("'{:<8}'".format(str))  # 左寄せ
print("'{:^8}'".format(str))  # センタリング
print("'{:>8}'".format(str))  # 右寄せ
```

出力

```text
'hello   '
' hello  '
'   hello'
```

## 数値

`d`は省略可(`:>8`でも大丈夫)

```python
print("{:d}".format(val))
print("{:>8d}".format(val))  # 右寄せ8桁
print("{:08d}".format(val))  # 0埋め8桁
```

```text
254
     254
00000254
```

### 小数

`f`は省略すると表示がおかしい

```python
val = 21.2345678
print("{:.4f}".format(val))   # 小数4桁
print("{:8.3f}".format(val))  # 全8桁・小数3桁
```

出力

```text
21.2346
  21.235
```

また、内部で型のチェックは行われており、小数の値に対して`d`で書式指定しようとするとエラーとなる

```python
print("{:d}".format(val))   # 整数
```

結果

```
Traceback (most recent call last):
  File "./print2.py", line 27, in <module>
    print("{:d}".format(val))   # 整数
ValueError: Unknown format code 'd' for object of type 'float'
```

キャストすれば動く

```python
print("{:d}".format(int(val)))   # 整数
```

### 基数変換

```python
val = 254
print("{:04x}".format(val))  # hex
print("{:04X}".format(val))  # HEX
```

出力

```text
00fe
00FE
```

### 桁区切り

```python
val = 16777216
print("{:,d}".format(val))
```

出力

```text
16,777,216
```

## %書式

実は`printf()`同等の%を使った書式も使える。(ただし`format`の方が間違いにくいということで`format`の使用が推奨されている)

```python
val = 21.2345678
print("%08.3f" % val)
print("%08d" % val) # こっちはcastなしで大丈夫
print("%8s" % str)
```

出力

```text
0021.235
00000021
   hello
```

## f文字列

Python3.6以降では、`format`に変わるf文字列という機能が導入されている。
それ以前のバージョンでは使用できないので注意。
基本的に`format`で書かれたコードは書き直せる。…と思う。

`format`では文字列中は`{}`と記述し、変数は引数で指定していたが、f文字列では`{}`内に変数名を記述するようになる。

```python
name = "くれりん"
print(f"こんにちわ、{name}さん。")

# 文字列
str = "hello"
print(f"'{str:<8}'")  # 左寄せ
print(f"'{str:^8}'")  # センタリング
print(f"'{str:>8}'")  # 右寄せ
# 数値
val = 254
print(f"{val:d}")
print(f"{val:04x}")   # hex
print(f"{val:04X}")   # HEX
print(f"{val:>8}")  # 右寄せ8桁
print(f"{val:08}")  # 0埋め8桁
# 小数
val = 21.2345678
print(f"{val:.4f}")   # 小数4桁
print(f"{val:8.3f}")  # 全8桁・小数3桁
# 式
print(f"{1+5*5:d}")
```

出力

```text
こんにちわ、くれりんさん。
'hello   '
' hello  '
'   hello'
254
00fe
00FE
     254
00000254
21.2346
  21.235
0026
```



---

- 参考
    - [組み込み型 — Python 3.7.3 ドキュメント / str.format(*args, **kwargs)](https://docs.python.org/ja/3/library/stdtypes.html#str.format)
    - [［Python入門］文字列の書式指定 (1/4)：Python入門 - ＠IT](https://www.atmarkit.co.jp/ait/articles/1904/23/news015.html)
    - [Pythonのprint関数で文字列、数値および変数の値を出力 | note.nkmk.me](https://note.nkmk.me/python-print-basic/)
    - [Python, formatで書式変換（0埋め、指数表記、16進数など） | note.nkmk.me](https://note.nkmk.me/python-format-zero-hex/)