変数置換を使用した評価と実行

変数置換を使用した評価と実行

サーバーを起動するステートメントを実行したいと思います。これには、起動するサーバーを決定する環境変数があります。私は次のコマンドを出発点にしました。

eval "exec gunicorn --chdir /this/dir package.sub:call_main() -b 0.0.0.0:80"

起動するサーバーが複数あるので、スクリプトをパラメータ化したいと思います。検索をちょっと試してみると、その引用文が次のようになることがわかりました。追加。だから私が今持っているのは次のとおりです。

APP=main
eval exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

理想的syntax error near unexpected token '('には、このような基本的なパラメータを持ちたいのですが、${APP:-main}構文エラーの問題が解決されれば可能だと思います。

上記のステートメントに間違ったことはありますか?また、evalここではこれが必要ですか?exec

答え1

2番目のコードでは、パラメータの周りの二重引用符を削除しましたeval。しないでください。これを削除すると、()シェルが特別になります(サブシェルが起動します)。

代わりに:

app=main
eval "exec gunicorn --chdir /this/dir package.sub:call_$app'()' -b 0.0.0.0:80"

eval文字列を再評価するときは、ここで括弧を引用する必要があります。$app呼び出し前に変数拡張が実行されます。eval

または、

app=main
eval "exec gunicorn --chdir /this/dir 'package.sub:call_$app()' -b 0.0.0.0:80"

これはもっと良く見えるかもしれません。

とは、変数名(たとえば)で有効な直後の文字を除いて、${APP}すべての点で同じです。ここでは必要ありません。また、既存の環境変数との予期しない競合を回避するには、小文字の変数名を使用します。$APP"${APP}x"{...}

私はここでは必要evalないと思いますexec。文字列は、以下を使用してeval再評価する必要はないようです。exec変える現在のシェルプロセスgunicorn(これがあなたが望むものかどうかわかりません)。

十分かもしれない

app=main
gunicorn --chdir /this/dir "package.sub:call_$app()" -b 0.0.0.0:80

二重引用符に注意してください。

関連:

答え2

あなたは複雑な仕事をしています。シェルは11のパスを作成する必要があります(そして各パスは次のステップに進むために入力を破壊します)。

あなたのコードは

APP=main
eval exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

理解するには、evalを削除してください。

exec gunicorn --chdir /this/dir package.sub:call_${APP}() -b 0.0.0.0:80

注:最初の例と同様に、二重引用符を削除してもeval同じ出力を取得できます。

これで予約しました()(この場合、トークンが誤って解釈される可能性がないため、特別です。プレフィックスがない場合はコマンドコンテキストにはありません(したがって括弧を使用してサブシェルを呼び出します)。見ると、なぜこれが起こるのかがわかります(そしてシェルパーサーはずっと前に設計されているので簡単です)。

したがって、()を次のパーサステップに渡すようにシェルに指示する必要があります。

エスケープ()を使用できます\

exec gunicorn --chdir /this/dir package.sub:call_${APP}\(\) -b 0.0.0.0:80

または引用:

exec gunicorn --chdir /this/dir package.sub:call_${APP}'()' -b 0.0.0.0:80

注:「単語」(パラメータ)全体を引用する必要はなく、一部を引用するだけです。これにより、一重引用符は必要ありません${APP}(拡張が必要です)。

最初の例では、二重引用符で引用できます。

eval "exec gunicorn --chdir /this/dir \"package.sub:call_main()\" -b 0.0.0.0:80"

このようにして、evalは外部引用符を削除し、execは内部引用符を表示します(エスケープされていません)。

関連情報