パイプのコマンド/運用演習

パイプは、左のコマンドの標準出力を右の標準入力へつなぎます。文字列をシェルの命令に変える機能ではありません。行の抽出、並べ替え、集計を小さなコマンドの組合せで行います。

この単元で学ぶこと

  • パイプのデータの流れと標準エラーの扱いを説明する
  • コマンドの順序による結果差を求める
  • 終了ステータスとサブシェルの基本を確認する

本文解説

出力を次の入力へ printf "red\nblue\nred\n" | grep red | wc -lは2を表示します。printfが3行を出し、grepが一致する2行を渡し、wcが改行を数えます。中間ファイルを作らず接続できますが、各コマンドの受取データと出力形式が一致していることが必要です。シェルが文字列redを命令として実行するわけではありません。

引数と標準入力は異なる printf "abc\n" | wc -cは4バイトを数えますが、printf "abc\n" | echo DONEはDONEです。echoは通常、標準入力を読まず引数を出力します。右に置けば必ず左のデータを加工する、とは限りません。各コマンドが標準入力を読むか、ファイル名や引数が必要かを確認します。

標準エラーは別経路 通常の|がつなぐのは標準出力です。{ printf "ok\n"; printf "bad\n" >&2; } | wc -lではwcの入力はokだけなので1です。badは標準エラーへ出ます。2>&1で標準エラーを標準出力と同じ行き先へつなぐと、両方をパイプへ渡せます。Bashの|&も両方を渡す記法です。

抽出と集計の順序 printf "b\na\nb\n" | uniqはb,a,bのままです。uniqは隣接する同じ行をまとめるためです。sort | uniqならa,bへまとまります。grep ERROR | wc -lは該当行数で、文字列ERRORの出現回数とは限りません。同じ行にERRORが二度あっても、grepの通常出力はその一行です。

リダイレクトとの優先関係 printf "x\n" > result.txt | wc -lではprintfの標準出力がファイルへ向くため、wcは0行を読みます。パイプ接続を作った後、個々のコマンドのリダイレクトが適用されます。逆にprintf "x\n" | wc -l > count.txtなら件数がファイルへ保存されます。どのコマンドの出力先を変えたかを追います。

終了ステータスを知る Bashでは通常、パイプラインの終了ステータスは最後のコマンドのものです。false | trueの直後の$?は0。左側の失敗を検知したい場合はpipefailを有効にすると、失敗したコマンドのうち一番右のステータスを使います。教材の既定状態では無効です。無条件に全処理成功を表す値と思い込まないようにします。

変数の変更が戻らない例 通常のBashでlastpipeが無効のとき、パイプ内の各コマンドはサブシェルで動きます。x=old;printf "new\n" | read x;printf "%s" "$x"では親のxはoldのままです。read自体が失敗したとは限らず、変更された環境が違います。lastpipe等の設定で扱いが変わるため、設問には設定を明記します。

段階的に確認する 専用の入力をprintfで作り、まずgrepまで、次にsortまで、最後にwcまでを実行して中間結果を確かめます。終了値が必要なら他のコマンドを実行する前に$?やBashのPIPESTATUS配列を保存します。末尾のheadが先に入力を閉じると上流がSIGPIPEになることもあり、pipefailの非ゼロを常に元データ破損と判断しません。

図解

データと診断を別の経路で追う
パイプは診断まで自動的に転送するわけではない。

重要ポイント

  • |は標準出力を標準入力へつなぐ。
  • 標準エラーを渡すなら明示的に統合する。
  • 通常の終了ステータスは最後のコマンド。
  • 順序と各コマンドの入出力の意味を追う。

間違えやすい点

  • 右側のコマンドが入力を読むとは限らない。
  • grepの行数と一致箇所数を混同しない。
  • サブシェル内の代入が親へ反映すると思い込まない。

用語解説

パイプ
コマンド間の標準出力と標準入力を接続する機構。
標準エラー
通常の出力と別に診断等を出す経路。ファイル記述子2。
終了ステータス
コマンド終了時の数値。通常0が成功を表す。
サブシェル
親とは別の実行環境であり、変数変更が親へ戻らない。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。