PowerShell の練習で、GitHub の releases のダウンロード数を表示するコードを書いてみた。
$url = "https://api.github.com/repos/$owner/$repos/releases" curl $url | ConvertFrom-Json | ForEach-Object { foreach ($p in $_.assets){ Write-Host $p.name $p.download_count } }
ところが次のようなエラーになってしまう。
$ ~\Download-Count.ps1 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 107k 0 107k 0 0 204k 0 --:--:-- --:--:-- --:--:-- 205k ConvertFrom-Json: C:\Users\hymkor\Download-Count.ps1:26 Line | 26 | curl $url | ConvertFrom-Json | ForEach-Object { | ~~~~~~~~~~~~~~~~ | Conversion from JSON failed with error: After parsing a value an unexpected | character was encountered: u. Path '[5].body', line 1059, position 5.
curl で取得したデータがおかしいのかと思って、一度、ファイルに落として Get-Content tmp.json | ConvertFrom-JSON
をしてみたところ、こちらはエラーにならない。
試行錯誤してみたところ、次のように書けば期待どおり動作した。
$url = "https://api.github.com/repos/$owner/$repos/releases" curl $url | nkf32 -W8 -s | ConvertFrom-Json | ForEach-Object { foreach ($p in $_.assets){ Write-Host $p.name $p.download_count } }
どうやら、「外部コマンド | 内部コマンド」というパイプラインを作ると、外部コマンドの出力は現在のコードページの文字コード、つまり CP932 などと解釈されてしまうためのようだ。
ところが curl はデータをあくまでバイナリデータとして、そのまま標準出力に吐いてくるので、GitHub 由来のデータは UTF8 なのだ。つまり、文字コードが誤認される結果となっていた。
PowerShell も 7.4 で「外部コマンド | 外部コマンド」がうまく動作するようになったが、まだまだ外部コマンドがからむパイプラインは鬼門のようだ。
これ最終的には curl.exe など使わず、PowerShell の機能でデータをダウンロードするよう直すべきなんだろうなぁ。
→ こんな感じで落ちついた
$url = "https://api.github.com/repos/$owner/$repos/releases" Invoke-WebRequest -URI $url | ConvertFrom-Json | ForEach-Object { foreach ($p in $_.assets){ Write-Host $p.name $p.download_count } }