web-dev-qa-db-ja.com

「猫の無用」に関する一般的な合意は何ですか?

Grep、sed、trなどの複数のUNIXコマンドをパイプ処理する場合、catを使用して処理される入力ファイルを指定する傾向があります。 cat file | grep ... | awk ... | sed ...のようなものです。

しかし最近、これが猫の役に立たない使用であると私の回答にいくつかのコメントが残された後、私はここで質問をすると思いました。

私は問題を調べて、 UUOCThe Useless Use of Cat Award に関するウィキペディアの記事に出くわしました。効率の観点からです。

私がここで遭遇した最も近い質問は次の質問でした: 猫に電話するのはもったいないですか? –しかし、私が求めていることはまったく同じではありません。

UUOCキャンプがcmd1 args < file | cmd2 args | cmd3 ..を使用すること、またはコマンドにファイルから読み取るオプションがあり、その後ファイルを引数として渡すことを提案していると思います。

しかし、私にとってはcat file | cmd1 ... | cmd2の方が読みやすく、理解しやすいようです。入力ファイルをさまざまなコマンドに送信するさまざまな方法を覚える必要はなく、プロセスは論理的に左から右に流れます。最初の入力、次に最初のプロセス...など。

猫の無用な使用についてどのような議論がなされているのか理解できていませんか? 2秒ごとに実行される大量の処理を実行するcronジョブを実行している場合、その場合、猫は無駄になる可能性があることを理解しています。しかし、それ以外の場合、猫の使用に関する一般的な合意は何ですか?

41
arunkumar

それをそのように使用しても他のことは何も達成されないという意味では役に立たず、おそらくより効率的なオプションでは達成できません(つまり、適切な結果が生成されます)。

ただし、catcat somefileよりもはるかに強力です。 man catに問い合わせるか、または この回答で書いたもの をお読みください。ただし、1つのファイルの内容だけが確実に必要な場合は、catを使用してファイルの内容を取得しないことで、パフォーマンスが向上する可能性があります。

読みやすさに関しては、これはあなたの個人的な好みに依存します。同じ理由で、特にパフォーマンスの面が無視できる場合は、catingファイルを他のコマンドに含めるのが好きです。

また、スクリプトの内容によっても異なります。それがあなた自身のシェルであり、あなたのデスクトップマシンのための便利な方法であるなら、あなた以外の誰も気にしないでしょう。チェーンの次のツールがシークできるほうがいい場合に遭遇し、これを頻繁に使用されるソフトウェアとして、パフォーマンスの低いルーターまたは同様のデバイス上の最小限のLinuxシステムの一部の最小Linuxシステムで配布すると、処理能力、それは違います。それは常にコンテキストに依存します。

21
Daniel Beck

毎日のコマンドラインの使用では、それほど大きな違いはありません。特にcatを使用しないことでCPUの時間が回避され、CPUがアイドル状態になるため、速度の違いに気付くことはありません。何百、何千、または何十万ものアイテムをループしていても、実用的には大きな違いはありません。非常に負荷の高いシステム(平均負荷/ N CPU> 1)を使用している。

ゴムが道に出会う場所とは、良い習慣を形成し、悪い習慣を思いとどまらせることです。カビの生えたクリシェを引きずり出すために、悪魔は細部にいます。そして、平凡な人と偉大な人を区別するのは、このような詳細です。

それは車を運転しているときのようなものですが、代わりに3つの権利を与えることができるのになぜ左折するのでしょうか。もちろんできますし、完璧に動作します。しかし、左折の力を理解していれば、3つの権利はばかげているように思えます。

1つのファイルハンドル、17kのRAM=およびCPU時間0.004秒を保存することではありません。UNIXを使用することの全体的な哲学についてです。私の図の「左回転の力」は単なるものではありません入力をリダイレクトすることは、それがUNIXの哲学です。

17
bahamat

例ではcat file | myprogramをよく使用します。猫を無用に使用していると非難されることがあります( http://www.iki.fi/era/unix/award.html )。次の理由で同意しません。

何が起こっているのかを理解するのは簡単です。

UNIXコマンドを読み取るときは、コマンドの後に引数が続き、リダイレクトが続くことが期待されます。リダイレクトはどこにでも可能ですが、めったに見られないため、人々は例を読むのが難しくなります。私は信じている

    cat foo | program1 -o option -b option | program2

より読みやすいです

    program1 -o option -b option < foo | program2

リダイレクトを最初に移動すると、次の構文に慣れていない人を混乱させます。

    < foo program1 -o option -b option | program2

そして、例は理解しやすいはずです。

簡単に変更できます。

プログラムがcatから読み取ることができることがわかっている場合は、通常、STDOUTに出力するすべてのプログラムからの出力を読み取ることができると想定できるため、独自のニーズに合わせてプログラムを適合させ、予測可能な結果を​​得ることができます。

STDINが通常のファイルでない場合、プログラムが失敗しないことを強調します。

program1 < fooが機能する場合、cat foo | program1も機能すると想定するのは安全ではありません。しかし、実際にはであり、反対のことを想定しても安全です。このプログラムは、STDINがファイルの場合は機能しますが、入力がパイプの場合は、シークを使用するため失敗します。

    # works
    < foo Perl -e 'seek(STDIN,1,1) || die;print <STDIN>'

    # fails
    cat foo | Perl -e 'seek(STDIN,1,1) || die;print <STDIN>'

http://oletange.blogspot.dk/2013/10/useless-use-of-cat.html のパフォーマンスペナルティを見てきましたが、結論はcat file |を使用しないことです処理の複雑さが単純なgrepに似ていて、読みやすさよりもパフォーマンスが重要な場合。他の状況ではcat file |で問題ありません。

14
Ole Tange

UUOCであるとコメントしている人の一部が取っている立場は、Unixとシェルの構文を本当に理解している場合、そのコンテキストでcatを使用しないことだと思います。文法がおかしいように見えます。文法がおかしくても文を書くことができますが、それでも私の理解を深めることができますが、言語に対する理解が不十分であること、ひいては教育が不十分であることも示しています。つまり、UUOCであると言うことは、誰かが何をしているのか理解していないと言う別の方法です。

効率に関して言えば、コマンドラインからパイプラインを実行している場合、cat somefile |を使用する方が効率的かどうかを考えるよりも、マシンが< somefileを実行するのにかかる時間が短くなります。それは問題ではありません。

12
garyjohn

今日、新人が私の回答の1つとしてUUOCを私に固定しようとしたときまで、この賞に気づきませんでした。 cat file.txt | grep foo | cut ... | cut ...でした。私は彼に一片の心を与え、そうした後に初めて、彼は賞の起源とそうすることの実践について言及してくれたリンクを訪れました。さらに検索したところ、この質問につながりました。意識的な配慮にもかかわらず、やや残念なことに、私の根拠を含む回答はありませんでした。

彼を教育するとき、私は防御するつもりはありませんでした。結局のところ、私の若い頃は、コマンドをgrep foo file.txt | cut ... | cut ...と書いていたでしょう。頻繁にシングルgrepsを実行するたびに、ファイル引数の配置がわかり、最初の引数がパターン以降はファイル名です。

私がcat接頭辞を付けて質問に答えたとき、それは部分的には「美味しさ」の理由(Linus Torvaldsの言葉で)が理由で、主に機能の説得力のある理由のためでした。

後者の理由の方が重要なので、最初に説明します。ソリューションとしてパイプラインを提供するとき、それは再利用可能であると期待しています。パイプラインが最後に追加されるか、別のパイプラインに接合される可能性は非常に高いです。その場合、grepにファイル引数を指定すると再利用性が台無しになり、ファイル引数が存在する場合はエラーメッセージなしでsilentlyを実行する可能性があります。 I. e。 grep foo xyz | grep bar xyz | wcは、xyzbarの両方を含む行の数を予想しながら、fooの行数にbarを含めます。使用する前にパイプライン内のコマンドの引数を変更する必要があると、エラーが発生しやすくなります。それにサイレント障害の可能性を追加すると、それは特に油断のならない習慣になります。

前者の理由はどちらも重要ではありません。なぜなら、多くの「良い味」は、上記の静かな失敗のようなものに対する単なる直感的な潜在意識の根拠であり、教育を必要とする人が「しかしその猫は役に立たない」。

ただし、先ほど述べた「いい味」の理由も意識してみます。その理由は、Unixの直交設計の精神に関係しています。 grepcutではなく、lsgrepではありません。したがって、少なくともgrep foo file1 file2 file3はデザイン精神に反します。直交する方法はcat file1 file2 file3 | grep fooです。現在、grep foo file1grep foo file1 file2 file3の特殊なケースにすぎず、同じように扱わないと、少なくとも無駄な猫賞を回避しようとする脳のクロックサイクルを使い果たしています。

これにより、grep foo file1 file2 file3が連結され、catが連結されるため、cat file1 file2 file3が適切ですが、catcat file1 | grep fooに連結されないため、したがって、catと全能のUnixの両方の精神を侵害しています。そうだとすれば、Unixは1つのファイルの出力を読み取り、それをstdoutに吐き出すために別のコマンドが必要になります(ページ番号を付けたり、単なる標準出力に吐き出したりするのではありません)。つまり、cat file1 file2と言ったり、dog file1と言ったり、cat file1を避けて賞を取得したり、dog file1 file2を避けたりすることを心がけてください。 of dogは、複数のファイルが指定されている場合にエラーをスローします。

うまくいけば、この時点で、ファイルをstdoutに吐き出すための個別のコマンドを含めず、他の名前を付けるのではなく連結するためにcatを付けることについて、Unixデザイナーに同情します。 <edit>このような犬、不幸な<演算子があります。残念ながら、パイプラインの最後に配置すると、簡単に構成できなくなります。最初に配置するための構文的または審美的にクリーンな方法はありません。また、一般的ではないので残念です。犬から始めますが、前のファイルの後に処理したい場合は、別のファイル名を追加するだけです。 (一方で>は半分ほど悪くはありません。最後にほぼ完全に配置されます。通常、パイプラインの再利用可能な部分ではないため、記号で区別されます。)</edit>

次の質問は、それ以上の処理をせずに、単にファイルまたは複数のファイルの連結をstdoutに吐き出すコマンドを使用することが重要なのはなぜですか? 1つの理由は、標準入力で動作するすべてのUnixコマンドが、少なくとも1つのコマンドラインファイル引数を解析し、存在する場合は入力として使用する方法を知ることを回避するためです。 2番目の理由は、ユーザーが次のことを覚えておく必要がないようにするためです。(a)ファイル名の引数の場所。 (b)上記のサイレントパイプラインのバグを回避します。

これで、grepに追加のロジックがある理由がわかります。根拠は、頻繁に使用され、スタンドアロンベースで(パイプラインとしてではなく)コマンドにユーザーが流暢になるようにすることです。これは、使いやすさを大幅に向上させるための直交性のわずかな妥協です。すべてのコマンドをこのように設計する必要はなく、頻繁に使用されないコマンドはファイル引数の余分なロジックを完全に回避する必要があります(余分なロジックは不必要な脆弱性(バグの可能性)につながることに注意してください)。例外は、grepの場合のようにファイル引数を許可することです。 (ちなみに、lsには、ファイル引数を受け入れるだけでなく、かなり必要とする理由がまったく異なります)

最後に、標準入力が利用可能な場合、grep(必ずしもlsとは限らない)などの例外的なコマンドがエラーを生成する場合は、より適切に実行できます。ユーザーの便宜のために、コマンドには全能のUnixの直交精神に違反するロジックがコマンドに含まれているため、これは妥当です。ユーザーの利便性を高めるため、i。 e。サイレント障害による被害を防ぐために、このようなコマンドは、サイレント障害の可能性がある場合にユーザーに警告することにより、自分の違反に違反することをためらわないでください。

5
randomstring

猫の無用な使用を擁護して

(この慣習に対するしつこいコメントの津波のバランスをとるためのいくつかの段落)

シェルとして、また小さなスクリプトのスクリプト言語として(そして残念ながらそれほど小さくないスクリプトに対して)何年もbashを使用してきました。ずっと前に、「猫の無用な使用」(UUoC)について学びました。私はまだ有罪少なくとも毎週ですが、率直に言って、それを避けることを余儀なくされています。私はcat< fileの使用は技術的な違いよりも好みに関するものであると信じており、catに対する私の好みを共有するLinuxの新しい人々が何かがあると考えないように保護するためにこの答えを書きました彼らのやり方について深刻な誤りを犯している(そして、そこにあるいくつかの状況に注意してください)。 Linus Torvaldsと同様に、スキルよりも味覚の方が重要であると私は思います。それは私の味があなたの味よりも良いという意味ではありませんが、何か味が悪い場合に価値のあるものを手に入れることなしにそれをやらないということです。

質問の著者のように私は感じますbashのようにREPLここで、複雑なコマンドを段階的に作成して問題を調査します。ここに、非常に典型的な例を示します。テキストファイルがあり、それについてあまり詳しくありません。cat fileと入力して、内容を確認しますIf出力が多すぎる場合は上矢印を押し、状況に応じて| headまたは| grep fooを追加しますまたは| what_ever処理ステップを追加して前のコマンドを拡張します。この方法では、単純なコマンドから次の処理ステップを追加することでより複雑なコマンドに段階的に進むことができます(私も同じようにしています) ipythonと私はpyfunctionalと同様のプログラミングツールがこのスタイルを包含する方法が大好きです。bashシェルで作業するとき[〜#〜] i [〜#〜]フローを中断してcatを削除することは役に立たないと確信していますtha nそれを存続させ、苦しめる...ケースの99.9%でまったく結果はありません。

もちろん、スクリプトを書くときはmight変更します。しかし、スクリプトを書いているときでも、UUoCをあざける人はこの重要な教訓をすばらしい心で無視していると思います:「時期尚早な最適化はすべての悪の根源です」 。また、通常とは異なる作業を行っていない場合、最適化が必要な場所にUUoCを配置するのは非常に困難です。もちろん、あなたは間違いなくそれを知る必要があります(それについて言及しているように見えるので、BTWは余分なプロセス呼び出しです)。プロセスを呼び出すのにコストがかかるまれなシステム(一部の組み込みシステムやCygWinの程度が低いなど)で作業する場合、その知識があれば、特別な状況で必要な場合の対処法を知ることができます。たとえば、ループで1秒間にcatを何度も呼び出すことに気付いた場合(BTWがその位置にいる場合は、bashがそのジョブに適切なツールかどうかを自問してください)繰り返しますが: "最初に正しく機能させ、必要に応じて最適化します"

そしてUUoCニックに関する不満の津波をどう説明しますか?

誰もが私の好みを持っているわけではないのに、UUoCについて不平を言う人の大部分は技術的ではなく人間的であると私は信じています。ほとんどのUnix初心者は< file commandイディオムを知らないので、経験豊富な人は「Old Guru」をプレイします。彼はまた、派手な言葉(「プロセスの呼び出し」)を使用し、「最適化」の親愛なる主題に触れる機会もあります。良い印象が保証されるので、抵抗するのは非常に困難です。次に、初心者は額面通りにグルのアドバイスを受け取り、長い間、「唯一の真実」として他の人にそれを再現します(そしてこの回答に反対投票します:-)。おもしろいメモ:UUoCの非効率を回避するためにbashを修正するのはおそらく非常に簡単なので、何年も経って誰もこの機能を追加したり< filename catをファイルにしたりしないのはなぜか疑問に思われるでしょう。暗い魂は、一部のグレイビアードバッシュハッカーが私たちをからかう機会を残したいと思うことを示唆するでしょう;-)

2
ndemou

本当にいいのは、次のような構文をサポートするシェルです。

< filename cmd | cmd2 cmd2arg1... | cmd3

その間、私はcat filename | realcmd1...は、引数としてファイル名を必要とする初期コマンドで標準化された構文を維持するため、許容されます。

1
user94124

猫は「においがする」または「読みやすい」ので、猫の使用は容認できると言う人すべてにとって、私はこれだけを言うでしょう:

多分あなたに…しかしあなたのコードを読んだり理解しようとするかもしれない他の人にではない。例を使って他の人に指示したり、コードを共有したりすることが絶対にない場合は、ぜひご自分の時間にそれを使用してください。

私はまた、このコメントを追加します。これは、長い間Linuxユーザーであり、管理者/エンジニアでもあります(そして私たちの多くがいます)。どうして?それは私たちがリソースを厳しく制御するシステム上のリソースを使用するからです。 catコマンドとパイプ自体は、まったく役に立たない余分なメモリとファイルハンドルを使用します。私のシステムが無料で必要とするリソースを拘束し、これらのリソースの使用法を説明できる何も得ていません。これは巨大です。

ここで私はここに座って、コードの匂いや読みやすさなどを1日中誰とでも議論できますが、結局のところ、それは書き込みまたは誤りの問題であり、システムのリソースを使用して何も得られないときはいつでも...違います。

ホームユーザーとして、私のアドバイスから学び、より良い方法を学ぶことができます。または、猫の「匂い」に盲目になることを選択することもできますが、この方法を公然と使用すると、呼び出されます。この練習では常にそうであり、あなたは静かにそれらが正しいことを認めなければならず、それは本当だから頑固です。 :-)

0
David Dreggors