[解決済み] 猫の無駄遣い?
質問
これはおそらく多くのFAQにあるもので、使用する代わりに
cat file | command
(これはcatの無駄な使い方と呼ばれる)正しい方法であるはずです。
command < file
2 番目の、quot;正しい" 方法では、OS は追加のプロセスを生成する必要はありません。
それを知っていながら、私は 2 つの理由で無駄な猫を使い続けました。
-
より美的に - データが左から右へだけ一様に動くのが好きです。そして、より簡単に
cat
を他の何かで置き換えるのも簡単です (gzcat
,echo
...)、2つ目のファイルを追加したり、新しいフィルタを挿入する(pv
,mbuffer
,grep
...). -
私は、場合によっては速くなるかもしれないと感じました。 2つの処理があるため、より速く、1つ目の処理(
cat
) が読み込みを行い、2 番目が何かを行うからです。 そして、それらは並列に実行することができるので、より速く実行することができます。
私のロジックは正しいですか(2番目の理由)?
どのように解決するのですか?
私は、今日までこの賞のことを知りませんでした。
UUOC
をつけようとした新人がいました。それは
cat file.txt | grep foo | cut ... | cut ...
. 私は彼に自分の考えを伝え、そうして初めて、彼がくれた賞の起源とその慣習に言及したリンクを訪れました。さらに検索を続けた結果、この質問にたどり着きました。意識して考えてみたものの、残念ながら、どの回答にも私の根拠は含まれていませんでした。
私は、彼に答えるにあたって、身構えるつもりはなかったのです。結局のところ、私の若い時代には、コマンドを次のように書いていたことでしょう。
grep foo file.txt | cut ... | cut ...
というのは、頻繁にある単一の
grep
を繰り返すたびに、ファイル引数の配置を学習し、最初のものがパターンで、後のものがファイル名であることが既知の知識となっているからです。
を使うのは意識的な選択でした。
cat
を使うことを意識的に選択したのです。
後者の理由がより重要であるため、私はそれを最初に出します。私がパイプラインをソリューションとして提供するとき、それが再利用可能であることを期待します。パイプラインが他のパイプラインの末尾に追加されたり、他のパイプラインに接続されたりすることはよくあることです。そのような場合、grepにファイルの引数を与えると再利用性が損なわれます。
無言で
ファイル引数が存在する場合、エラーメッセージを表示することなく、行います。I. e.
grep foo xyz | grep bar xyz | wc
で何行目かを知ることができます。
xyz
には
bar
の両方を含む行の数を期待しているのに対して
foo
. パイプラインのコマンドを使用する前に引数を変更しなければならないのは、エラーが発生しやすいものです。それに加えて、サイレントエラーの可能性もあり、特に陰湿な行為となります。
前者の理由も重要で、多くの " 良い味 "。 というのは、上記の無言の失敗のように、教育を必要とする人が「でも、あの猫って役に立たないよね」と言った瞬間に思いつかないような、直感的な潜在意識による理由付けに過ぎないのです。
しかし、前者の「センスがいい」という理由も意識してみることにします。その理由は、Unix の直交設計の精神に関係しています。
bar
は
grep
と
cut
は
ls
. したがって、少なくとも
grep
は設計精神に反しています。直交するやり方は
grep foo file1 file2 file3
. では
cat file1 file2 file3 | grep foo
の特殊なケースに過ぎません。
grep foo file1
であり、もしあなたがそれを同じように扱わないのであれば、少なくともあなたは無駄な猫賞を避けようとして脳のクロックサイクルを使っていることになります。
という議論につながります。
grep foo file1 file2 file3
は連結であり
grep foo file1 file2 file3
は連結しているので、適切なのは
cat
が適切ですが
cat file1 file2 file3
が連結されていないため
cat
の両方の精神に違反していることになります。
cat file1 | grep foo
と全能のUnixの両方の精神に違反することになります。もしそうなら、Unix は一つのファイルの出力を読んで標準出力に吐き出すために別のコマンドを必要とするでしょう(ページ分割や何かではなく、純粋に標準出力に吐き出すだけです)。つまり、次のような状況になるわけです。
cat
または、次のように言います。
cat file1 file2
を避け、意識的に
dog file1
を避けながら、賞をもらうために
cat file1
のデザインがうまくいけばいいのですから。
dog file1 file2
は複数のファイルが指定された場合、エラーを投げるからです。
うまくいけば、この時点で、ファイルを標準出力に吐き出す個別のコマンドを含めない Unix 設計者に共感していただけると思いますが、同時に
dog
を他の名前をつけるのではなく concatenate と名づけたことです。
cat
の不正確なコメントを削除しました。
<edit>
は、実際には
<
はパイプラインの最初に位置する標準出力にファイルを吐き出すための効率的なノーコピー機能なので、Unixの設計者はこのために特別なものを含めました。
<
次の質問は、単にファイルやいくつかのファイルの連結を標準出力に吐き出すだけで、それ以上の処理を行わないコマンドを持つことがなぜ重要なのでしょうか。1 つの理由は、標準入力で動作するすべての Unix コマンドが、少なくとも 1 つのコマンド ライン ファイルの引数を解析する方法を知っていて、それが存在する場合は入力として使用することを避けるためです。もう一つの理由は、ユーザが以下のことを覚える必要がないようにするためです。(a) ファイル名の引数がどこに行くのか、(b) 前述のサイレント パイプライン バグを回避するためです。
そこで、なぜ
</edit>
が余分なロジックを持つ理由です。その理由は、頻繁に使用されるコマンドのために、ユーザーの流動性を確保するためです。
スタンドアロン
ベースで (パイプラインとしてではなく) 頻繁に使用されるコマンドについて、ユーザーの流動性を確保するためです。これは、使いやすさを大幅に向上させるために、直交性をわずかに妥協したものです。すべてのコマンドがこのように設計されるべきではありませんし、頻繁に使用されないコマンドは、ファイル引数の余分なロジックを完全に避けるべきです(余分なロジックは不必要な脆弱性(バグの可能性)につながることを覚えておいてください)。例外として、ファイル引数を許可する場合は
grep
. (ちなみに
grep
はファイル引数を受け入れるだけでなく、かなり必要とする全く別の理由があることに注意してください)
最後に、より良くできたこととして、もし
ls
(ただし、必ずしも
grep
) は、ファイル引数が指定されたときに標準入力も利用可能であれば、エラーを発生させます。
関連
-
[解決済み] Git上でシェルコマンドを実行する際に使用するSSH-keyの秘密鍵を指定する方法は?
-
[解決済み] シェルスクリプトでブール変数を宣言して使用するにはどうすればよいですか?
-
[解決済み] grep --exclude/--include構文を使って特定のファイルをgrepしないようにする
-
[解決済み] grepを使ってフォルダ内の単語を検索するにはどうすればよいですか?
-
[解決済み] Windowsでcatの代わりになるものはありますか?
-
[解決済み】catを使ってファイルの最初の行を読むにはどうすればいいですか?
-
[解決済み] linuxのcatコマンドは、ファイルへのテキスト書き込みに使用できますか?
-
[解決済み] フィッシュシェルで環境変数を設定する方法
-
[解決済み] grep --includeオプションを複数のファイルタイプに使用するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Bashでファイルの中身をループする
-
[解決済み] Unixでテキストファイルからあらかじめ決められた範囲の行を抽出するには?
-
[解決済み] if not true条件」を作るには?
-
[解決済み】LinuxのコマンドラインからSHA-256ハッシュを生成する方法
-
[解決済み] テキストファイルから改行を削除するにはどうすればよいですか?
-
[解決済み] ファイルの最初の行以降で正規表現にマッチする部分を取得する方法
-
[解決済み] bashでwcから整数値だけを取得する
-
[解決済み] フィッシュシェルで環境変数を設定する方法
-
[解決済み] grep --includeオプションを複数のファイルタイプに使用するにはどうすればよいですか?