
grep
sed
ファイル名引数を指定すると、stdinは無視されます。
$ echo foo > test.txt
$ echo foobar | grep f test.txt
foo
$ echo foobar | sed -e 's/foo/bar/' test.txt
bar
これが確立されたベストプラクティスですか?では、なぜそうなのでしょうか?
答え1
プログラムは、ファイルがコマンドラインで指定されているかどうかを知っています。 stdinで利用可能な入力があるかどうか(読み取ろうとすることに加えて)知る方法はありません。入力がある場合、プログラムはその入力が意図されているかどうかを知る方法はありません。したがって、唯一合理的なオプションは、プログラムの呼び出し方法(コマンドライン引数、環境変数、設定ファイルなど)に基づいてstdinから読み取るかどうかを決定するための明示的な規則を持つことです。
たとえば、一般的なテキストユーティリティ(cat
、、、、、、 ...)は、ファイルが指定sort
されていない場合はstdinから読み取られ、ファイルが指定された場合は指定されたファイルから読み込まれます。インタプリタは同様の規則に従います。たとえば、指定されたファイルからコマンドを読み込んでいる間は、引数なしで標準入力からコマンドを読み込みます(または必要に応じてスクリプトにstdinを読み取らせます)。入力ファイル名が予想される場所で発生した場合、プログラムがstdinから読み取る一般的な規則もあります。grep
awk
perl -p
sh
sh script_file_name
-
次のシェルの断片を考えてみましょう。
somecommand | while read line; do
process "$line"
done
process
標準入力から読み取るかどうかを知る必要があります。 「stdinが提供されているかどうかをテストする」のようなものはありません。 stdinが提供されていますが、呼び出しプログラムのユーザーはstdinを読みたいかどうかを知っています。
答え2
私が見つけた答えはそれが設計された方法でした。標準入力とファイルからデータを読み取るには、echo foobar | grep f - test.txt
.from を使用します。man grep
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.