次のBash
スクリプトを実行すると、Hello
が出力されるはずです。代わりに、空白行を出力して終了します。
echo 'Hello' | echo
piping
からecho
へのecho
出力が機能しないのはなぜですか?
echo
は、すべての引数を出力します。 stdin
からは読み取りません。したがって、2番目のecho
は、Hello
のstdin
を無視して、すべての引数(なし)を出力して終了します。
stdin
を読み取り、それをstdout
に出力するプログラムの場合、cat
を使用します。
$ echo Hello | cat
Hello
パイプを理解していないようです。この場合、名前がないため(named pipes)もあるため、anonymousパイプとしてより正確に知られています。匿名パイプは、たとえば同じ親を持つプロセスなど、関連するプロセス間でのみ機能します。
パイプは、Cランタイムライブラリに起因するIOシステムの一部です。これらのストリームはデフォルトでバッファリングされます(例外があります)。基本的に、パイプは、あるプロセスの出力バッファーを別のプロセスの入力バッファーに接続するだけです。
使用される最初の3つのストリーム(ファイル記述子と呼ばれる)には、0、1、および2の番号が付けられます。最初の0は、標準入力、またはstdin
(Cで使用される名前)。デフォルトではこれはキーボードに接続されていますが、<
シンボルまたはパイプの右側にあるプログラム名を使用してリダイレクトできます。
2番目の1は、標準出力またはstdout
として知られています。デフォルトでは、これは端末画面に接続されていますが、>
シンボルまたはパイプの左側にあるプログラム名を使用してリダイレクトできます。
そう:
echo 'Hello' | echo
echo
から標準出力を取得し、echo
の標準入力に渡します。しかし、echo
は標準入力を読みません!だから何も起こりません。
フィルタープログラムは、コマンドラインで指定されたファイル名を処理します。ファイル名が指定されていない場合、標準入力を読み取ります。例には、cat
、grep
、およびsed
が含まれますが、notecho
です。例えば:
echo 'Hello' | cat
「Hello」と表示され、cat
は役に立たない(多くの場合)。
echo 'Hello' | cat file1
echo
からの出力をignoreし、file1の内容のみを表示します。 stdinは、ファイル名が指定されていない場合にのみ読み取られることに注意してください。
これは何を表示すると思いますか?
echo 'Hello' | cat < file1 file2
なぜ?
最後に、3番目のストリーム2はstandard errorまたはstderr
と呼ばれ、これはunbufferedです。パイプはstdinとstdoutの間でのみ動作するため、無視されます。ただし、stdoutを使用するようにstderrをリダイレクトできます(man dup2
を参照):
myprog 2>&1 | anotherprog
2>&1
は、「ファイル記述子2をファイル記述子1と同じ場所にリダイレクトする」ことを意味します。
上記は通常の動作ですが、プログラムは必要に応じてすべてをオーバーライドできます。たとえば、ファイル記述子2から読み取ることができます。 process substitutionやhere documentsなどの他の形式のリダイレクトなど、他の多くの詳細は省略しました。
パイプは、stdinから入力を受け取るコマンドに対してのみ実行できます。ただし、エコーはstdinから取得しません。引数から入力を取得して出力します。したがって、これは機能しません。エコーするには、echo $(echo 'hello')
のようなことができます
echo
(ビルトインと/bin/echo
の両方)がstdin
から何も読み取らないためです。
代わりにcat
を使用します。
echo 'Hello' | cat
Hello
またはパイプなし:
cat <<< 'Hello'