PowerShell: ダブルクォートを`""`でエスケープする際、空白の有無によってエスケープの結果が変わる
動作環境
- Windows 10
- PowerShell 5.1.19041.1151
- Python3.8
やりたいこと
コマンドラインの引数に、JSON文字列を渡したいです。
JSON文字列にはダブルクォートが含まれているので、何らかの対応が必要です。
たとえばbashの場合は、JSON文字列をシングルクォートで括れば、JSON文字列内のダブルクォートをコマンドライン引数に正しく渡すことができます。
サンプルとして、1番目の引数を出力するPythonスクリプトを実行します。
import sys
print(sys.argv[1])
$ python print_arg1.py '{"x": 1}'
{"x": 1}
同じようなことを、WindowsのPoerShellでも行いたいです。
問題
以下の記事を流し読みして、「JSON文字列内のダブルクォートをエスケープするには、ダブルクォートを連続で記述すればよい」と解釈しました(正しくない気がする)。。
JSON文字列内のダブルクォートを連続で記述して、pythonコマンドを実行しました。
# エスケープされない
PS > python .\print_arg1.py '{"x": 1}'
{x: 1}
# エスケープされた
PS > python .\print_arg1.py '{""x"": 1}'
{"x": 1}
# エスケープされない?!
PS > python .\print_arg1.py '{""x"":1}'
{x:1}
JSON文字列内に空白が存在するとエスケープされ、空白が存在しないとエスケープされませんでした。
原因?
原因は分かりませんでしたが、以下の質問の回答に、関係ありそうな文がありました。
Powershell will auto-quote (enclose in <">) a single argument string, if it contains spaces and the spaces don't mix with an uneven number of (unsescaped) double quotes.
解決方法
ダブルクォートをバックスラッシュでエスケープすることで解決しました。
PS > python .\print_arg1.py '{\"x\":1}'
{"x":1}
https://stackoverflow.com/questions/53490414/how-to-pass-json-string-data-to-powershell 参考
補足
コマンドプロンプトの場合
# ==== JSON文字列をシングルクォートで括る ====
# NG
> python .\print_arg1.py '{"x": 1}'
'{x:
# NG
> python .\print_arg1.py '{""x"": 1}'
'{x:
# NG
> python .\print_arg1.py '{""x"":1}'
'{x:1}'
# NG。
> python .\print_arg1.py '{\"x\":1}'
'{"x":1}'
# NG。JSON文字列内に空白があると、途中までしか表示されない
> python .\print_arg1.py '{\"x\": 1}'
'{"x":
# ==== JSON文字列をダブルクォートで括る ====
# OK
>python .\print_arg1.py "{\"x\": 1}"
{"x": 1}
# OK。JSON文字列内に空白がなくてもエスケープされる
>python .\print_arg1.py "{\"x\":1}"
{"x":1}
# OK
>python .\print_arg1.py "{""x"": 1}"
{"x": 1}
# OK。JSON文字列内に空白がなくてもエスケープされる
>python .\print_arg1.py "{""x"":1}"
{"x":1}
コマンドプロンプトの場合は、ダブルクォートをバックスラッシュまたはダブルクォートでエスケープした上で、JSON文字列をダブルクォートで括る必要があるようです。
PowerShellでJSON文字列をダブルクォートで括った場合
PowerShellの場合はシングルクォートで括るのが正しいのですが、念のためダブルクォートで括ったときの動きも確認します。
PS > python .\print_arg1.py "{"x": 1}"
{
PS > python .\print_arg1.py "{""x"": 1}"
{x: 1}
PS > python .\print_arg1.py "{""x"":1}"
{x:1}
PS > python .\print_arg1.py "{\"x\": 1}"
{\
Discussion