いくつかの結果を生成するbashアプリケーションがあり、stdout
ユーザーが選択したファイルに結果をエコーしたいと思います。他の対話型メッセージも画面に表示されるため、>
結果をファイルに表示しようとするときにユーザーに明示的にリダイレクトを使用するように要求することはオプション(*)ではありません。そのメッセージもファイルに表示されるためです。
これで解決策がありましたが、見苦しいです。
if [ -z $outfile ]
then
echo "$outbuf" # Write output buffer to the screen (stdout)
else
echo "$outbuf" > $outfile # Write output buffer to file
fi
私は、toおよび他のものと$outfile
同じ変数を持つことを試みましたが、実際にstdoutに書き込むのではなく、その名前のファイルにのみ書き込みます。よりエレガントなソリューションはありますか?stdout
&1
(*) こんな目的でだまされて使うこともできますが、stderr
それも醜いと思いますか?
答え1
まず、あなたはecho
任意のデータ出力を防止。
Linuxベースのシステム以外のシステムでは、次のものを使用できます。
logfile=/dev/stdout
Linuxでは、これはいくつかのタイプのstdoutで動作しますが、stdoutがソケットの場合は失敗します。または、stdoutが通常のファイルの場合、stdoutが現在作成されているファイルの場所にあるのではなく、ファイルが切り捨てられます。
それ以外の場合、Bourneのようなシェルには方法はありませんホームフレーズリダイレクト(次が利用可能eval
)
eval 'printf "%s\n" "$buf" '${logfile:+'> "$logfile"'}
変える変える、専用使用可能ファイル記述子:
exec 3>&1
[ -z "$logfile" ] || exec 3> "$logfile"
printf '%s\n' "$buf" >&3
これの1つの(マイナーな)欠点は、ksh
fd 3を除いて、スクリプトで実行されるすべてのコマンドでリークされることです。を使用すると、代わりにアクションを実行zsh
できますが、それに対応するアクションはありません。sysopen -wu 3 -o cloexec -- "$logfile" || exit
exec 3> "$logfile"
bash
別の一般的なイディオムは、次の関数を使用することです。
log() {
if [ -n "$logfile" ]; then
printf '%s\n' "$@" >> "$logfile"
else
printf '%s\n' "$@"
fi
}
log "$buf"
答え2
- 設定
outfile
。"/dev/stdout"
- ユーザーがファイル名を選択または上書きするか、
outfile
デフォルト値をそのままにします。 printf '%s\n' "$outbuf" >"$outfile"
私が使うprintf
理由は、「なぜprintfがechoより優れているのですか?」。
このソリューションに関する注意事項については、以下を参照してください。Stefan Chazerasの答え。
答え3
この試み
#!/bin/bash
TOSCREEN="1" # empty OR 0 to log to file
if [[ ! -z "$TOSCREEN" && $TOSCREEN == "1" ]]; then
echo "$outbuf" # Write output buffer to the screen (stdout)
else
if [[ ! -f $outfile ]]; then
#echo -e "Making file "
touch "$outfile"
fi
echo "$outbuf" >> $outfile # Write output buffer to file
fi
答え4
#!/bin/bash -ue
function stdout_or_file()
{
DUMP_FILE=${1:-}
if [ -z "${DUMP_FILE}" ]; then
# print stdin to stdout
cat
else
# dump stdin to a file
sed -n "w ${DUMP_FILE}"
fi
}
echo "foo" | stdout_or_file "${outfile}"
これは${1:-}
bashに固有のもので、「-u」モードで特に便利です。他のシェルでも動作する一般的なシングルライナーは次のとおりです。
echo "foo" | if [ -z "${outfile}" ]; then cat; else sed -n "w ${outfile}"; fi