文字列の Bash コマンドは、後で使用するのではなく、文字列を作成するときに実行されます。

文字列の Bash コマンドは、後で使用するのではなく、文字列を作成するときに実行されます。

私はシェルスクリプトに初めて触れましたが、エクスプロイトをほぼ完了しました。FTPプログラム。スクリプトで問題があるのは、長いコマンドのリスト(で区切り;)を生成するときです。

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done

私が気づいたのは、tailスクリプトで後でコマンド文字列を呼び出すのではなく、forループが繰り返されるとプログラム(バックティックで囲まれた)が実行されることです。

残念ながら、このステップでは $somefile の内容を調べる準備ができていません。文字列が生成されるのではなく、必要なときにコマンドが実行されるようにするにはどうすればよいですか?

答え1

これは少しトリッキーです。 Haukeが提供する情報は正確です。ユースケースに基づいて分析します。

最も簡単な方法は、変数定義が定義に含まれるコマンドを$()実行しないようにエスケープ構文を使用することです。ネストされたコマンドが実際に実行されるときにシェルで$最終結果を再評価(通過)する必要があることに注意することが重要です。$()eval

例を見るのははるかに簡単なので、次の例を見ると正しい方向に行くことができます。

for((i=0;i<10;i++)); do 
  date +%s.%N  # Print a timestamp (in format seconds.nanoseconds)
  test="echo \$(date +%s.%N)" # Save a command to do the same
  sleep 1      # Sleep for a second
  eval "$test" # Evaluate the command saved in variable 'test'
  echo         # Print a new line before the next iteration
done

以下は、上記の例のサンプル出力です(1回の繰り返しで切り捨て)。

1398832186.133661344
1398832187.139076728

各ループの2番目のタイムスタンプは、最初のタイムスタンプから約1秒であることがわかります。逆に、定義$でエスケープtestや削除なしで同じテストを実行すると、両方のevalタイムスタンプがほぼ一致します。

ほとんどの状況でそれを使用する習慣を持ち上げないでくださいeval。しかし、これは避ける良い方法を知らない状況の1つです。お役に立てば幸いです。頑張ってください!

答え2

引用にはいくつかのレベルがあります。二重引用符("...")はスペースと複数の特殊文字(~、、、、、...)を保護しますが、パラメータの拡張やコマンドの置き換えを防ぐことはできませ&|;

'「危険な」文字の前に一重引用符()またはバックスラッシュを追加する必要があります。

通常、バックティックを代わりに使用することを検討する必要があります$(tail ...)。バックティックは古い標準ですが、私たちは$()ほとんどの人に問題を引き起こさない非常に古い標準について話しています。新しいバージョンは読みやすく、入れ子にすることができます。 sxのフォーマットの問題は言うまでもありません...

関連情報