概要
なんか、よく分からない状況になったので、忘れないうちにメモメモ。。。
たまたま、バイナリデータを標準入力から受け取って処理するプログラムを書いていたのですが
Powershell (pwsh) でデータを渡そうとしても
> ./app < data.bin ParserError: Line | 1 | ./app < data.bin | ~ | The '<' operator is reserved for future use.
なんか、エラーになった。なるほど。現状は <
のリダイレクトは使えないんですね。それは仕方ない。
んで、調べると以下のようにするみたい。
> Get-Content data.bin -Raw | ./app
上のようにすると動いたのですが、なんか結果がおかしいのです。
実際のプログラムとは違いますが、以下のようなプログラムがあるとします。
package main import ( "fmt" "io" "os" ) func main() { b, _ := io.ReadAll(os.Stdin) fmt.Println(len(b)) for _, v := range b { fmt.Printf("%02x,", v) } fmt.Println("") }
単純に受け取ったバイト列の長さとデータを出力しているだけのプログラムがあったとします。
んで、以下のようにバイナリデータを作ったとします。
$ echo -n "0000000: 0102 0304 FFFF" | xxd -r - data.bin
hexdump で確認すると
$ hexdump data.bin 0000000 0201 0403 ffff 0000006
当然こうなります。んで、これを前述のプログラムにLinuxのシェル上で食べさせると
$ ./app < data.bin 6 01,02,03,04,ff,ff,
こうなる。
で、同じようにして pwsh で食べさせると
$ pwsh PowerShell 7.2.1 Copyright (c) Microsoft Corporation. https://aka.ms/powershell Type 'help' to get help. > $PSVersionTable Name Value ---- ----- PSVersion 7.2.1 PSEdition Core GitCommitId 7.2.1 OS Linux 5.4.0-1067-azure #70~18.04.1-Ubuntu SMP Thu Jan 13 19:46:01 UTC 2022 Platform Unix PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…} PSRemotingProtocolVersion 2.3 SerializationVersion 1.1.0.1 WSManStackVersion 3.0 > Get-Content data.bin -raw | ./app 11 01,02,03,04,ef,bf,bd,ef,bf,bd,0a,
なんで?? 最後の 0a はLFでしょう。(動かしているのはLinuxです)
なんで改行勝手に付与すんの?ってのは置いといて FF FF の部分がなんか変わってる・・・。バイナリのサイズも変わっとるし。
をみると Start-Process xxxx -RedirectStandardInput xxxx.bin
ってやるのがいいって書いてあるので試してみると
> Start-Process ./app -RedirectStandardInput data.bin 11 01,02,03,04,ef,bf,bd,ef,bf,bd,0a,
やっぱり駄目。
てことで、個人的には pwsh で外部プログラムに対してのパイプとかリダイレクトとかはしないほうがいいのかなって思いました。テキストデータだったら多分大丈夫なのでしょう。(勝手に改行付与されそうですが)
補足
しばたさんのブログで情報を発見。貴重な情報をアップしてくださり感謝。
エンコーディングが絡んでいるみたいですね。そのまま処理してくれたら嬉しいのに。。
上記のしばたさんのブログ記事でも
挙動の謎さと性能面の問題があることからPowerShellから外部のプロセスに対してパイプラインを渡すのはやめておいた方が賢明だと思います。
と書かれていました。勉強になりました m(_ _)m
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。