paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

シェルのコマンド置換を入力リダイレクトとして渡す方法はプロセス置換だった

シェルでターミナル内でちょっとした操作や、シェルスクリプトを作るときコマンド置換はよく使うと思います。
これを入力ダイレクトとして使いたかったのですがどうにもできず長年tmpファイルを作って凌いでいたのですが、プロセス置換という機能を知りこちらで実現できました。

コマンド置換

※ubuntu24のzsh環境で試してます。

実行後の結果を渡してくれるやつですが正式にはコマンド置換というらしいです。
バッククォートとか$()で囲むやつですね。

TODAY=`date`echo $TODAY
2025927日 土曜日 14:55:06 JST
❯ echo $TODAY is today
2025927日 土曜日 14:55:06 JST is today

実行結果を入力リダイレクトで渡したい

簡単な抽出とか文字列作成をターミナル内で済ませようと思って入力リダイレクトを使いたい時があるじゃないですか。

while read line ; do echo $line is today ; done < $TODAY
zsh: そのようなファイルやディレクトリはありません: 2025927日 土曜日 14:55:06 JST
❯
❯ while read line ; do echo $line is today ; done < `date`
zsh: そのようなファイルやディレクトリはありません: 2025

でも入力リダイレクトで使おうとするとファイルがありませんというエラーが出ます。
まあ実際ファイルじゃないしな、ということでこの手の作業はtmpファイルとかを作って処理してました。

プロセス置換

いろいろ調べていったら<()で囲むとプロセス置換というものになり一時ファイルとして扱えるようです。
Linuxを触り始めてから結構経ってますが全然知らない機能でした。なぜ今まで知らなかったのだ。

プロセス置換についてGeminiに聞いたら以下の回答をくれました。

プロセス置換(Process Substitution)は、シェル(主にBashやZsh)の高度な機能の一つで、コマンドの入出力を一時的なファイルのように扱えるようにする構文です。
コマンド置換が「コマンドの出力」を「文字列」として展開するのに対し、プロセス置換は「コマンドの入出力」を「ファイルパス」として展開します。

プロセス置換は一時的なファイルパス(特殊なファイル)を作成することで、パイプラインをファイルディスクリプタのように扱えるようにする機能です。

というわけでプロセス置換を使ってみると入力リダイレクトが成功しました。

while read line ; do echo $line is today ; done < <(date)
2025927日 土曜日 15:04:47 JST is today

ファイルから呼んだってことになり正常に出力されるわけですね。
なるほど。これはいいですね。

本来使おうと思っていた用途

上記はサンプルまでに簡単なコマンドにしましたが、本来はシェルスクリプトの改修をしておりその中で使う用に調べてました。

以下の電話帳のようなフィールドが全部埋まっていないファイルがあって、一列しかない不完全な行を省く処理をしてからメイン処理に渡したかったのです。
プロセス置換を知るまではtmpファイルを作って省いてからメイン処理に咬ませていたのですが、すでにtmpファイルがいくつもあるスクリプトだったのでファイルを増やしたくなかったんです。

宇宙 太郎       0X0-4444-5555
伝説 の勇者
七転 八起       0X0-9876-1234
爆誕 次郎
天才 プログラマー       0X0-1122-3344
令和 の侍       0X0-5566-7788
神 風子
炎上 博士       0X0-6666-8888
飯 旨太郎       0X0-1234-5000
最強 の一般人

これをプロセス置換で処理すれば、

while read line ; do echo $line ; done \
< <(awk -F "\t" '{if (NF > 1) {print $NL}}' phone_dict.txt)
宇宙 太郎       0X0-4444-5555
七転 八起       0X0-9876-1234
天才 プログラマー       0X0-1122-3344
令和 の侍       0X0-5566-7788
炎上 博士       0X0-6666-8888
飯 旨太郎       0X0-1234-5000

と一次処理した結果に対してさらに処理できるわけです。しかも実ファイルなしで。素晴らしい。
これはいいものを知りました。シェルは本当に奥が深いですね。
今更知ったのも恥ずかしいですがこれからは便利なプロセス置換も活用していきたいと思います。

参考サイト

Bash リダイレクトまとめ #Bash - Qiita

bashのプロセス置換で遊んでみよう! | Raccoon Tech Blog [株式会社ラクーンホールディングス 技術戦略部ブログ]