いつ入力リダイレクトを使用する必要がありますか?


21

次の2つのコマンドを使用して、同じ結果を生成しました。

[root@localhost ~]# grep line comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

[root@localhost ~]# grep line <comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

これらの2つのアプローチのいずれかがお互いにアプローチしている場合、長所/短所を教えてください。

回答:


28

man grepページから(Debianの場合):

説明

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.

最初の場合、grepファイルを開きます。第二に、シェルはファイルとの標準入力に割り当て、それを開くgrepと、grep任意のファイル名の引数を渡されていないことは、その標準入力をgrepする必要が想定しています。

1の長所:

  • grep 複数のファイルをgrepできます¹。
  • grepの各オカレンスlineが見つかったファイル名を表示できます。

2の長所:

  • ファイルを開くことができない場合、シェルは、より関連性の高い情報(スクリプト内の行番号など)を含むエラーを返します。grepそれを開きます。また、ファイルを開くことができない場合はgrep呼び出されません(一部のコマンドでは、多分そうではありませんgrepが、大きな違いを生む可能性があります)。
  • grep line < in > outin開くことができない場合、out作成または切り捨てられません。
  • 珍しい名前(-またはで始まるファイル名など)を持つファイルには問題ありません-
  • コスメティック:<fileコマンドラインのどこにでも配置して、コマンドフローをより自然に表示する<in grep line >outことができます。
  • 化粧品:GNU grepでは、ファイル名だけでなく、一致する行の前に使用するラベルを選択できます。

    <file grep --label='Found in file at line' -Hn line
    

パフォーマンスの観点から、ファイルを開くことができない場合、grepリダイレクトを使用する場合の実行を保存しますが、そうでない場合、grep大きな違いは期待できません。

リダイレクトを使用すると、への追加の引数を渡すために持っセーブgrep、あなたが作るgrepの引数は少し簡単に解析します。一方、シェルには、dup2()ファイル記述子0へのファイル記述子への(少なくとも)追加のシステムコールが必要です。

では{ grep -m1 line; next command; } < filegrep(ここではGNUがgrep)になるでしょうseek()ので、ちょうど一致する行の後に戻ってnext command(それはまた、ファイルがシークであるかどうかを判断する必要があります)、ファイルの残りの部分を見ています。言い換えれば、stdin内の位置はのもう1つgrepの出力です。を使用するとgrep -m1 line file、それを最適化できgrepます。


ノート

¹ではzsh、次のことができます。

grep line < file1 < file2

ただし、これはcat file1 file2 | grep linecatユーティリティを呼び出さずに)同等の処理を行うため、効率が低下します。最初のファイルが改行文字で終了せず、どのファイルでパターンが見つかったかがわからない場合は混乱を招く可能性があります。

²の場合ksh93bashいえ、などのファイルがある /dev/tcp/host/port(と/dev/fd/xではいくつかのシステムでbash)、リダイレクトのターゲットで使用される代わりに、実際のファイルシステム上のファイルを開くの特別な目的のためにシェルをインターセプト(ただし、一般的に、これらのファイルは、ファイルシステムに存在しない)。によって認識されるの/dev/stdinと同じ目的を果たしますが、少なくともここでは、より適切に名前空間が設定されています(誰でも任意のディレクトリで呼び出されるファイルを作成できますが、管理者のみが呼び出されるファイルを作成できます。-grep-/dev/tcp/host/port


+1、わかりやすい説明。疑問が1つあります。2番目のケースでは、シェルがファイルを開いたときに、開いたファイルの内容を標準入力(キーボード)に渡しますか?? (「grepの標準入力」という用語と混同されました)。
アンキット

1
@Ankit、stdinは、アプリケーションがデフォルトで入力を読み取る場所であり、ファイル記述子0です。端末では、fd 0は端末デバイス(/ dev / ttyxxまたは/ dev / pts / nなど)の読み取りから開かれます。それは彼らがあなたがキーボードでタイプしたものを得ることになる方法です。コマンドの標準入力のシェルリダイレクトは、コマンドを実行する前にfd 0を他のファイルに開くだけです。
ステファンシャゼル

6

StephaneChazelasの答えはをカバーしてgrep(1)おり、ほとんどのUnix系統コマンドはそのように機能しますが、すべてではありません。標準入力(キーボード、を介してリダイレクトされたファイル< file、または別のコマンドによってパイプされた出力、愚かな例ls * | grep '^ab*c$')から、または引数として指定されたファイルから読み取るのが標準grep comment file1 file2 file3です。一部のコマンドは、という名前のファイルがあることが慣例使用-あなたが言うことができますので、標準入力されmake-middle | cat head - tailてストリームを取得するためにhead何でも、gen-middle続く生成し、tail。これは、コマンドの使用に柔軟性を与えるための仕様です。

どちらが良いですか?それが機能する限り、cmd fileはより短いですcmd < file。シェルがファイルのフロビング()を実行するコマンドとそれ自体を実行するコマンドとの間にはわずかな時間差がありますが、<一日中何もしない限りおそらく気付かないでしょう。ステファンの答えで言及されているプロのような考慮事項に依存します。


cmd filecmd<fileしかしより短くはありません。
ステファンシャゼラス16

ただし、aを入力するにはShift キーを押す必要があると仮定すると、キーストロークは 1つ短くなります<
-DopeGhoti
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.