Bash スクリプトのリダイレクトは変数として使用できません。

Bash スクリプトのリダイレクトは変数として使用できません。

bashscriptで読み取り専用変数を設定しました。

readonly NO_OUTPUT="1>/dev/null 2>&1"

私のスクリプトの一部のコマンドでこの変数を使用すると、$ {NO_OUTPUT}がリスト内の他のファイルであると思うようなエラーが発生するのはなぜですか?

たとえば、次のようなものがあります。

make install ${MAKE_PREFIX} ${NO_OUTPUT}

最後に、次の内容でエラーが生成されます。 make: *** No rule to make target '1>/dev/null 2>&1'. Stop.

ただし、次のように変更すると:

make install ${MAKE_PREFIX} 1>/dev/null 2>&1

予想通り正確に動作しますか?

他のコマンド(cp、rmなど)でも同様の問題が発生しましたが、エラーが発生しました。

答え1

make install ${MAKE_PREFIX} ${NO_OUTPUT}

呼び出さmakeれるとinstall、分割+globの結果はMAKE_PREFIX変数の内容に適用され、分割+globの結果はNO_OUTPUT変数の内容に別々の引数として適用されます。

おそらくあなたは次のようなものが欲しいでしょう:

if [ -n "$VERBOSE" ]; then
  nooutput() { "$@"; }
else
  nooutput() { "$@" > /dev/null 2>&1; }
fi

nooutput make install "$MAKE_PREFIX"

内容が別の引数である MAKE_PREFIX 変数をmake呼び出すために使用され、詳細情報表示モードで実行されない場合、stdout および stderr が /dev/null にリダイレクトされます。install

ここで別名を使用することもできます。

if [ -n "$VERBOSE" ]; then
  alias nooutput=' '
else
  alias nooutput='> /dev/null 2>&1 '
fi

nooutput make install "$MAKE_PREFIX"

bashPOSIX以外のモードでシェルを使用している場合でもshopt -s expand_aliases

コードでエイリアスを使用するときにもエイリアスを定義する必要があります。読む(いいえ走る)。

では、zsh次のこともできます。グローバルエイリアスはコマンド位置になくても拡張されるため、次のようにできます。

if [ -n "$VERBOSE" ]; then
  alias -g '$NOOUTPUT$='
else
  alias -g '$NOOUTPUT$=> /dev/null 2>&1'
fi

make install "$MAKE_PREFIX" $NOOUTPUT$

$NOOUTPUT$代わりに、ここではパラメータ拡張は行われず、nullで置き換えられるか、コードを読み取るときにコードが評価されるかなり前に置き換えられること$NOOUTPUTをより明確にするためにここで使用されます。$NOOUTPUT$> /dev/null 2>&1

答え2

シェルは、各部分を拡張する前に各部分が何であるかを識別するために、コマンドラインから各単語(トークン、部分)を区切ります。リダイレクトは、コマンドライン解析フェーズの近くに設定されます。はるかに後で変数の拡張一つリダイレクトされた単語にはできません。

いいえ、配列変数や単純変数も機能しません。

$ NO_OUTPUT=( "1>/dev/null"    "2>&1" )
$ printf '%s\n' "${NO_OUTPUT[@]}"
1>/dev/null
2>&1

$ a="1>/dev/null"
$ b="2>&1"
$ printf '%s\n' "$a" "$b"
1>/dev/null
2>&1

$ printf '%s\n' 1>/dev/null 2>&1

$

したがって、いいえ。変数の内容をシェルワードトークンに変換する方法はありません。

とは別にeval。しかし、evalは通常セキュリティevilリスクがあります。

答え3

eval文字列を受け取り、コマンドとして実行するコマンドを使用すると、コードは次のようになります。

eval make install ${MAKE_PREFIX} ${NO_OUTPUT}

なぜこれが起こるのか、そしてあなたが望む結果を得るためのより良い方法については、以下を見てください。変数に格納されたコマンドをどのように実行できますか?

関連情報