web-dev-qa-db-ja.com

STDINとコマンドに渡される引数の違いは何ですか?

どちらかの形式を使用してcatメソッドを実行できます。

cat file_name
cat < file_name

結果は同じです

次に、manstdinの形式で実行します

man < file_name

file_nameに含まれるもの:

# file_name
cat

しかし、ポップアップWhat manual page do you want?を実行する代わりにman cat

catstdinを引数として受け入れることができたが、manは受け入れられない理由を知りたいです。そして、コマンドライン引数とstdinの違いは何ですか?

18
steveyang

あなたの質問は、使用しているシェルがコマンドラインでユーザー入力をどのように解析するかと密接に関連しています。

コマンドラインの最初のWordがプログラムであり、特別なフォルダー(ほとんどがPATHで定義されている)にあり、特殊文字が指定されていない場合(使用しているシェルによって異なります)、スペースまたはタブで区切られた後続のすべての単語が渡されます特別な形式、すなわち配列でプログラムに。各Wordを配列の1つの要素として。

プログラムがどのように呼び出すかは、(配列内にある)引数をどのようにプログラムするかによって異なります。引数の構文がどのように見えるかについては準標準がいくつかありますが、一般的にプログラマーは完全に自由です。したがって、最初の引数は、ファイルの名前、またはプログラマーがプログラムを作成したときにプログラマーが考えていたものとして解釈できます。

特殊文字_<_または_>_をコマンドラインに追加する場合、シェルは_<_および_>_を追加せず、後続の単語を配列に追加しませんプログラムに渡されます。シェルが_<_または_>_を指定すると、基盤となるカーネル(キーワード piping )によってサポートされる、ファンシーなものを作り始めます。何が起こっているのかを把握するには、STDINSTDOUTが何であるかを理解する必要があります(直接関係がないため、STDERRは省略しています)。

ターミナルに表示されるすべてのもの(ほとんどの場合、ディスプレイの一部)は、シェルまたは以前に起動した他のプログラムによって、特別なファイルに書き込まれます( nixすべてはファイル ) 。このファイルには特別なIDがあり、STDOUTと呼ばれます。プログラムがキーボードからデータを読み取りたい場合、キーボードを直接ポーリングしません(少なくともほとんどの場合)が、STDINと呼ばれる特別なファイルから読み取ります。内部的に、このファイルは標準入力デバイス、ほとんどの場合キーボードに接続されています。

解析されたコマンドラインでシェルが_<_または_>_を読み取る場合、対応するプログラムが実行されている間、シェルはSTDINまたはSTDOUTを特定の種類で操作します。 STDINSTDOUTは、もはやターミナルや標準入力デバイスを指すのではなく、コマンドラインの後続のファイル名を指します。

2行の場合

_cat file_name
cat < file_name
_

対応する開発者がcatSTDINからデータを読み取るか、ファイルからデータを読み取るため、観測された動作は同じです。名前は、最初のコマンドライン引数(シェルがcatに渡す配列の最初の要素)として指定されます。 。その後、シェルにcatを操作するように指示しないため、STDINは_file_name_またはSTDOUTのコンテンツ全体をターミナルに書き込みます。 2行目で、シェルはSTDINをこのように操作します。これは、標準入力デバイスを指すのではなく、現在の作業ディレクトリにある_file_name_というファイルを指すことを覚えておいてください。

ラインの他の場合

_man < file_name
_

manは、引数なしで呼び出された場合、つまり空の配列である場合、STDINから何かを読み取ることを意図したものではありません。だから行

_man < file_name
_

等しい

_man
_

たとえば、_-l -_をmanに渡すと、STDINmanから何かを読み取ります。コマンドラインでこのオプションを指定すると、manから読み取ったSTDINの内容を端末に表示できます。そう

_man -l - < file_name
_

(ただし、manは単なるページャーではなく、ファイルの入力を解析するため、ファイルの内容と表示される内容が異なる可能性があるので注意してください)。

したがって、STDINSTDOUT、およびコマンドライン引数の解釈方法は、すべて対応する開発者次第です。

私の答えが明らかになることを願っています。

21
user1146332

それらは完全に異なります。コマンドライン引数は配列でプログラムに渡され、プログラムはそれらを使って必要なことを実行できます。 stdinは、プログラムがデータを要求する必要がある入力ストリームです。ファイルを処理するプログラムは多くの場合、両方をサポートすることを選択しますが、手動でサポートする必要があります。ファイル名がコマンドライン引数として渡されたかどうかをチェックし、そうでない場合は代わりにstdinから読み取ります

manがstdinを読み取って、表示する必要のあるmanページを見つけることを期待しているようですが、これは非常に奇妙な動作です。いつそれを使用しますか? catがstdinを表示するという事実は、他に何もしないという事実のアーティファクトです。他のツールがそのように機能するとは思いません。たとえば、grepはファイル名を取得するかstdinから読み取ることができますが、stdinのデータを処理しますが、stdinからファイル名を読み取りませんそしてそれを開きます

この動作が本当に必要な場合は、xargsを使用できます。これにより、ファイルがコマンドライン引数に変換されます。

$ xargs man < file_name

または、cat呼び出し内にman呼び出しを埋め込むだけです。

$ man $(cat file_name)
12
Michael Mrozek