ファイルを入力として使用してさまざまなタスクを実行する大規模なスクリプトがあります。これはテストバージョンです:
echo "cat: $1"
cat $1
echo "grep: $1"
grep hello $1
echo "sed: $1"
sed 's/hello/world/g' $1
私のスクリプトでプロセス置換を使用できるようにしたいのですが、最初のコマンド(cat
)のみが機能し、残りは機能しません。パイプラインだからだと思います。
$ myscript.sh <(echo hello)
以下を印刷する必要があります。
cat: /dev/fd/63
hello
grep: /dev/fd/63
hello
sed: /dev/fd/63
world
可能ですか?
ベストアンサー1
この<(…)
構成はパイプを生成します。パイプは同様のfilenameを渡します/dev/fd/63
が、これは特別な種類のファイルです。実際にパイプを開くとは、ファイル記述子63をコピーすることを意味する。 (終了参照この回答もっと説明したい。 )
パイプから読むのは破壊的な仕事です。一度バイトをキャプチャすると、元に戻すことはできません。したがって、スクリプトはパイプの出力を保存する必要があります。一時ファイル(入力が大きい場合は優先)または変数(入力が小さい場合は優先)を使用できます。一時ファイルの使用:
tmp=$(mktemp)
cat <"$1" >"$tmp"
cat <"$tmp"
grep hello <"$tmp"
sed 's/hello/world/g' <"$tmp"
rm -f "$tmp"
(2つの呼び出しをcat
にまとめることができますtee <"$1" -- "$tmp"
。)変数の使用:
tmp=$(cat)
printf "%s\n"
printf "%s\n" "$tmp" | grep hello
printf "%s\n" "$tmp" | sed 's/hello/world/g'
コマンド置換は、$(…)
コマンド出力の末尾にある改行を切り取ります。これを防ぐには、文字を追加してから削除してください。
tmp=$(cat; echo a); tmp=${tmp%a}
printf "%s\n"
printf "%s\n" "$tmp" | grep hello
printf "%s\n" "$tmp" | sed 's/hello/world/g'
さて、変数置換の二重引用符を忘れないでください。