GNU/Linux >> Linux の 問題 >  >> Ubuntu

コマンド(つまりGrep)は、Glob拡張の一部として実行されるタイミングをどのように知るのですか?

私の理解によると、globワイルドカードはシェルによって解釈され、シェルは一致するファイル名ごとに指定されたコマンドを実行します。 abc1, abc2, and abc3というファイルがあるとします。 私の現在のディレクトリにあります。次に、たとえば、echo abc* 「abc」で始まるファイル名ごとに1回エコーします。

ただし、grep 'foo' abc*を実行すると 、これは実行する必要があると思います:

grep 'foo' abc1
grep 'foo' abc2
grep 'foo' abc3

つまり、次の出力を取得する必要があります(すべてのファイルに「foo」という1行が含まれていると仮定します):

foo
foo
foo

ただし、代わりに次のようになります:

abc1:foo
abc2:foo
abc3:foo

したがって、これには2つの考えられる説明があると思います。まず、どういうわけか、grepはglob式で使用されたことを検出し、一致する前にファイル名を出力することで応答します。次に、複数のファイルをgrepに渡すことができるため、シェルは実際には1つのコマンドのみを実行します。

grep 'foo' abc1 abc2 abc3

ただし、これが機能するのは、grepが最後に複数のファイルを受け入れるためです。別のコマンドでは1つのファイルしか渡されない可能性があります。したがって、グロブに一致する複数のファイルに対してコマンドを実行する場合、上記の2番目の方法でグロブが機能すると機能しません。

とにかく、誰かがこれに光を当てることができますか?

ありがとう!

承認された回答:

それが秘訣です。コマンドは認識していません。仕事をするのはシェルです

たとえば、grep 'abc' *.txtについて考えてみます。 。システムコールのトレースを実行すると、次のように表示されます。

bash-4.3$ strace -e trace=execve grep "abc" *.txt > /dev/null
execve("/bin/grep", ["grep", "abc", "ADDA_converters.txt", "after.txt", "altera_license.txt", "altera.txt", "ANALOG_DIGITAL_NOTES.txt", "androiddev.txt", "answer2.txt", "answer.txt", "ANSWER.txt", "ascii.txt", "askubuntu-profile.txt", "AskUbuntu_Translators.txt", "a.txt", "bash_result.txt", ...], [/* 80 vars */]) = 0
+++ exited with 0 +++

シェルが拡張された*.txt .txtで終わる現在のディレクトリ内のすべてのファイル名に 拡大。非常に効果的に、シェルはgrep 'abc' *.txtを変換します grep 'abc' file1.txt file2.txt file3.txt . . . 。したがって、2番目の仮定は正しいです。

最初の仮定は正しくありません–プログラムにはグロブを検出する方法がありません。 *を渡すことができます コマンドへの文字列引数として、しかしそれをどうするかを決めるのはコマンドの仕事です。ただし、ファイル名の拡張は、すでに述べたように、それぞれのシェルのプロパティです。

ただし、これが機能するのは、grepが最後に複数のファイルを受け入れるためです。別のコマンドでは、1つのファイルしか渡されない可能性があります。

まさにその通りです!プログラムは、受け入れ可能なコマンドライン引数の数を制限しません(たとえば、Cでは文字列の配列const char *args[] Pythonではsys.argv[] )、ただし、長さを検出できます その配列の、または予期しない何かが間違った配列位置にあるかどうか。 grep これは行わず、複数のファイルを受け入れます。これは仕様によるものです。

関連:Ubuntu 13.10にアップグレードした後、Firefoxがコンピューターをクラッシュさせることがありますか?

ちなみに、不適切な引用とgrepを使用したグロビングが問題になる場合があります。これを考慮してください:

bash-4.3$ echo "one two" | strace -e trace=execve grep *est*
execve("/bin/grep", ["grep", "self_test.sh", "test.wxg"], [/* 80 vars */]) = 0
+++ exited with 1 +++

準備ができていないユーザーは、grepがestの任意の行と一致することを期待します。 その中の文字はパイプから来ていますが、代わりにシェルのファイル名拡張がひねりを加えています。これは、ps aux | grep shell_script_name.sh 、プロセスが実行されていることを期待していますが、スクリプトがあった同じディレクトリからコマンドを実行したためです。 、シェルのファイル名拡張によりgrep 舞台裏でユーザーが期待したものとは完全に異なって見えるようにするコマンド。

適切な方法は、一重引用符を使用することです:

bash-4.3$ echo "one two" | strace -e trace=execve grep '*est*'
execve("/bin/grep", ["grep", "*est*"], [/* 80 vars */]) = 0
+++ exited with 1 +++

Ubuntu
  1. 変数に格納されているコマンドを実行するにはどうすればよいですか?

  2. ティーコマンドはどのように機能しますか?

  3. 同じ名前でエイリアスされた元のコマンドを実行するにはどうすればよいですか?

  1. Linuxgrepコマンドの使用方法

  2. シェルで設定された時間アプリケーションを実行する方法は?

  3. Wineが.exeファイルを自動実行しないようにする方法は?

  1. ディレクトリの内容が更新されたときにコマンドを実行するにはどうすればよいですか?

  2. Xdg-openコマンドは、ファイルを開くために使用するアプリケーションをどのように認識しますか?

  3. コマンド実行時にターミナル出力を非表示にする方法は?