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


10

私はシェルスクリプティングに比較的慣れていませんが、lftpプログラムを使用するスクリプトをほぼ完成させました。私が問題を抱えているスクリプトの部分は、コマンドの長い文字列(で区切られている;)を作成するときです。

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

私が気づいているのはtail、forループが反復しているときにプログラム(バッククォートで囲まれている)が実行されていることですが、スクリプトの後半でコマンドの文字列を呼び出したときではありません。

残念ながら、$ somefileの内容は、この段階ではまだ検査する準備ができていません。文字列の作成中にではなく、必要なときにコマンドを実行するにはどうすればよいですか?

回答:


8

これは少しトリッキーです。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と、2つのタイムスタンプはほぼ​​一致します。

evalほとんどの状況で使用する習慣を身につけないでください。しかし、これは私がそれを回避するための良い方法を知らない状況の1つです。うまくいけば、これが役立ちます。幸運を!


どうもありがとう、$(...)Haukeが提案したように使用してみましたが、バックスラッシュが重要です。
リッキー

助けてくれて嬉しいです-ただし、ここで重要なのはeval、エスケープせずにコマンドを囲むために二重引用$符(')ではなく単一引用符()を使用して同じことを実行できるためです"
daBeamer 14

Huakeの提案と同様に、今気づきました。lftpプログラムでこれを使用すると、エコーはコマンドを出力するだけで、実際には実行されません。より具体的なヘルプが必要な場合は、メーリングリストを試してみてください。
リッキー

実行しようとしているのはどのコマンドですか?echo遅延実行のネストされたコマンドの出力を含むコンテンツを含む文字列にしたいという印象を受けました。
daBeamer 2014

1
@Ricky @HaukeLagingのすべての点に同意する必要があります。そのままのコードではecho、コマンドevalはなく文字列であるため、機能しません。私たちにもっと適切な例があるなら、私たちは手助けしようとすることができます。
daBeamer 2014

6

引用にはいくつかのレベルがあります。二重引用符("...")プロテクト空白やいくつかの特殊文字(~&|;、...)が、パラメータ展開とコマンド置換を防ぐことはできません。

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

一般$(tail ...)に、バッククォートの代わりに使用することを検討する必要があります。バックティックは古い標準ですが$()、ほとんどの人にとって問題とならないほど古いものについて話しています。新しいバージョンは読みやすく、ネストすることができます。ここでsxのフォーマットの問題は言うまでもありません...


高速返信ハウケをありがとう。残念ながら、バックティックを推奨値に置き換えて$(...)も同じ結果が得られます-ストリングが定義されると、シェルがこれを実行します。
リッキー

@Rickyそれは別の提案ではありませんでした。使用$()する必要がありますが、とにかく一重引用符が必要です。
Hauke Laging 2014

それで、それらのキャラクターの組み合わせは私が求めているものを達成しませんか?
リッキー

@Ricky「どちらか一重引用符が必要」について理解するのが難しいのは何ですか。あなたは明らかにそれを試してさえいない。
Hauke Laging 14

実際にはそうしましたが、単一引用符を使用すると、エコーはその行のすべてを通常の文字列として出力します。例を提供することについて、それほど難しいことは何ですか?
リッキー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.