多くのコマンドラインユーティリティは、パイプから、またはファイル名の引数として入力を取得できます。長いシェルスクリプトの場合、特に最初のコマンドに複数行の引数が必要な場合は、チェーンをcat
で始めると読みやすくなります。
比較する
sed s/bla/blaha/ data \
| grep blah \
| grep -n babla
そして
cat data \
| sed s/bla/blaha/ \
| grep blah \
| grep -n babla
後者の方法は効率が悪いですか?もしそうなら、違いは、スクリプトが実行されるかどうか、たとえば1秒に1回実行されるかどうかを気にするのに十分ですか?読みやすさの違いはそれほど大きくありません。
ここにいくつかの欠点の要約があります:
_cat $file | cmd
_
以上
_< $file cmd
_
$file
_の周りには(意図的に説明するために)二重引用符が抜けています。 cat
の場合、それはzsh
を除いて常に問題です。リダイレクションの場合、これはbash
または_ksh88
_の場合のみの問題であり、他の一部のシェル(POSIXモードのbash
を含む)の場合は(スクリプトではなく)対話型の場合のみです。cmd
が組み込まれている場合、bash
のようないくつかのシェルでは2つのプロセスです。cat
が組み込まれているシェルを除いて、パフォーマンスの最前線にありますが、追加のコマンドも実行されます(もちろん、ロードされ、初期化されます(およびリンクされているライブラリも同様です))。cat
プロセスとcmd
プロセスを交互にスケジュールし、パイプバッファーを常にいっぱいにして空にする必要があります。 cmd
が一度に_1GB
_ large read()
システムコールを実行する場合でも、パイプは数キロバイトを超えるデータを保持できないため、制御はcat
とcmd
の間を行き来する必要があります。時間。cmd
s(_wc -c
_など)は、stdinが通常のファイルである場合に最適化を行うことができますが、そのstdinは単なるパイプであるため、_cat | cmd
_では実行できません。 cat
とパイプを使用すると、ファイル内でseek()
を実行できないことも意味します。 tac
やtail
などのコマンドの場合、これはパフォーマンスに大きな違いをもたらします。つまり、cat
では、入力全体をメモリに格納する必要があるということです。cat $file
_、さらにその正しいバージョン_cat -- "$file"
_は、_-
_(または_--help
_または_-
_で始まるすべてのような特定のファイル名では正しく機能しません。 _--
_)を忘れた場合。 cat
の使用を主張する場合、信頼性を高めるために、代わりに_cat < "$file" | cmd
_を使用する必要があります。$file
_を読み取り用に開くことができない(アクセスが拒否された、存在しない...)場合、_< "$file" cmd
_は一貫したエラーメッセージ(シェルによる)およびnot runを報告しますcmd
、_cat $file | cmd
_はcmd
を実行しますが、標準入力は空のファイルのように見えます。つまり、_< file cmd > file2
_などの場合、file
を開けない場合、_file2
_は破棄されません。パッティング<file
パイプラインの終わりは、cat file
開始時。自然英語は左から右に読みます。
パッティング<file
パイプラインの開始も猫よりも読みにくいと私は言うでしょう。 Wordは記号、特に間違った方向を指しているように見える記号よりも読みやすくなっています。
cat
を使用すると、command | command | command
フォーマット。
ここでの他の回答が直接対処していないように見えることの1つは、このようにcat
を使用しても、「無関係のcatプロセスが生成されて機能しない」という意味では「役に立たない」ということです。 「不必要な作業のみを行う猫プロセスが生成される」という意味では役に立たない。
これら2つの場合:
sed 's/foo/bar/' somefile
<somefile sed 's/foo/bar/'
シェルは、somefileまたはstdin(それぞれ)から読み取るsedプロセスを開始し、次にいくつかの処理を実行します-改行に到達するまで読み取り、その行の最初の 'foo'(存在する場合)を 'bar'で置き換えてから出力しますその行をstdoutにループします。
の場合:
cat somefile | sed 's/foo/bar/'
シェルはcatプロセスとsedプロセスを生成し、catのstdoutをsedのstdinにワイヤリングします。 catプロセスはファイルから数キロバイトまたはおそらくメガバイトのチャンクを読み取り、それを標準出力に書き込みます。そこで、sed sommandが上記の2番目の例のようにそこからピックアップします。 sedがそのチャンクを処理している間、catは別のチャンクを読み取り、それを標準出力に書き込んで、sedが次に処理できるようにします。
言い換えると、cat
コマンドを追加することで必要となる追加の作業は、追加のcat
プロセスを生成する追加の作業だけでなく、バイトの読み取りと書き込みの追加の作業でもあります。 1回ではなく2回ファイルします。さて、実際に言えば、最近のシステムでは、大きな違いはありません。システムが数マイクロ秒の不要な作業を行う可能性があります。しかし、配布する予定のスクリプトの場合、潜在的に能力不足のマシンでスクリプトを使用する可能性がある場合は、数マイクロ秒で多くの反復を合計できます。