これはなに?
シェルコマンドでパイプを繋いでやったことをDartに移植しようとして困ったことを解決したメモ
やりたいこと
シェルコマンドで以下のように複数のコマンドを組み合わせて結果を得るケースをDartでやる
dpkg -s PACKAGE | grep Version | sed -e 's/Version: \([0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/'
コマンド叩くとこんな感じの簡単なお仕事なので、これをそのまま子プロセス呼び出してパイプで繋げばええやんと思ったのが間違いだった。
結果
import 'dart:io';
import 'dart:convert';
class Package {
String? version;
Future<bool> Execute() async {
final dpkg = await Process.start('/usr/bin/dpkg', ['-s', PACKAGE]);
final grep = await Process.start('/usr/bin/grep', ['Version']);
dpkg.stdout.pipe(grep.stdin);
final sed = await Process.start('/usr/bin/sed', ['-e', 's/Version: \\([0-9]\\+\\.[0-9]\\+\\.[0-9]\\+\\).*/\\1/']);
grep.stdout.pipe(sed.stdin);
await sed.stdout.transform(utf8.decoder).forEach(reader);
return true;
}
void reader(String str) {
if (version == null) {
version = '';
}
version = '${version}${str.trimRight()}';
}
}
こんな感じでとりあえず version
に格納したい値はセットできた。
パイプの方法を調べるのにかなり時間がかかったので、この場合はdpkgのプロセスだけ実行して、その出力から目的の文字列の抽出はDartで書いた方がおそらく圧倒的に速く終わった。
ただ、食わせたいのがgrepやsedのような文字列置換には限らないので、今後何かしらパイプ繋いで処理した結果に対してDartで処理したい場合に役立つと思う。
役立つと思ったでしょ?実際Dartで標準入力から受け取るようにするプログラム書いて、シェルから最後にDartのプログラムにパイプしてやるのが楽だと思うよ!!!
こんな風にな!
cmd1 | cmd2 | cmd3 | DartApp
ということで
せっかくやりたいことは実現できたので、ここに供養しておきます
それでは良いDartライフを。