bashコマンドの代替出力がエスケープされるのを防ぐ方法は?

bashコマンドの代替出力がエスケープされるのを防ぐ方法は?

bashスクリプトでコマンド置換を使用して、次のように変数に基づいてリダイレクトシンボルを出力しようとしています。

IS_VERBOSE=false
curl $BLAH $( $IS_VERBOSE && echo '-i' || echo '> /dev/null' )

つまり、冗長な場合は-iスイッチを追加し、それ以外の場合は標準出力からすべてを削除します。問題はIS_VERBOSE偽のときに私のコマンドが

curl $BLAH \> /dev/null

より一般的には、コマンド置換は文字や> >> & | # $その他の文字をエスケープします。コマンド置換を使用してエスケープなしでこれらのシンボルを出力するにはどうすればよいですか?

答え1

置換が発生した後(POSIXでは「>」の前の左側のみをターゲットにすることができます)、「>」があるかどうか評価されなくなるため、目的のアプローチは機能しません。 。

POSIX準拠に興味がない場合(最終的には「bash」とタグ付けした場合)、右側を動的に設定して解決策を見つけることができますが、個人的にはまったく異なるアプローチをとります。以下で詳細に説明する。カスタムファイル記述子に基づいて詳細/自動モードを有効にします。https://stackoverflow.com/a/20942015/2261442

投稿から抜粋したコードは、次の様子を示しています。

# Some confirmations:
printf "%s\n" "This message is seen at verbosity level 3 and above." >&3
printf "%s\n" "This message is seen at verbosity level 4 and above." >&4
printf "%s\n" "This message is seen at verbosity level 5 and above." >&5

答え2

私はこれがあなたの脱出問題を解決しないことを知っています(可能であるかどうかはまだわかりません)。男の巻き、これはあなたが望むことを達成します:

BLAH=localhost

IS_VERBOSE=true
OPTIONS="-o /dev/null"
$IS_VERBOSE && OPTIONS=""

curl $BLAH -s $OPTIONS
    <html>
    <p>hi</p>
    </html>

IS_VERBOSE=false
OPTIONS="-o /dev/null"
$IS_VERBOSE && OPTIONS="-i"

curl $BLAH -s $OPTIONS

後者は何も出力しません。他のシェル(bash、shなど)への依存性が少なく、移植性が優れています。

答え3

Bashのマニュアルによると、シェルの拡張順序は次のとおりです。中括弧拡張、チルダ拡張、パラメータおよび変数拡張、コマンド置換、算術拡張、トークン化、パス名拡張。また、コマンドが実行される前、つまりシェル拡張後にリダイレクトが発生することが示されています。したがって、次のコマンドは意味があります。

redir='>'
echo value $redir file

そして

echo value $(echo '>') file

発売予定ファイルに文書

残念ながら、コマンドラインが最初に解析され、リダイレクトトークンがただこの段階で決定しました。後でコマンドを実行する前に、これらのトークンに基づいてリダイレクトが実行されます。

eval curl $BLAH $( $IS_VERBOSE && echo '-i' || echo '> /dev/null' )

これはコマンドを再分析してリダイレクトを識別する方法で機能しますが、使用するのがやや難しく、予期しない動作を引き起こす可能性があるシェル拡張も実行します。

メモ:>$varBashには合計の特別な処理があります。>&$var

関連情報