Bash - 一重引用符を追加するコマンドの置き換え

Bash - 一重引用符を追加するコマンドの置き換え

深刻なアクセントを評価するときにbashの動作に問題があります。オプションの-nameを使用してfindを実行したいと思います。

find -name "*.log"

うまくいきますが、入れ子になったスクリプトから-name部分を取得したい場合

find `echo "-name \"*.log\""`

まったく動作しません。 bash -xで実行すると、コマンドが次のように評価されることがわかります。

find -name '"*.log"'

明らかに一重引用符のためだと思います。これを取り除くための回避策はありますか?ありがとうございます。

//要求されたオペレーティングシステムとbashバージョン:Debian、7.8 wheezy、Bash 4.2.37(1)-release

答え1

Bashはまだコマンドに一重引用符を追加しません。表示される単一引用符は、コマンドに有効なbash構文が表示されるように追加されました。見たら

find -name '"*.log"'

これは、bashがこのコマンドを実行するように指示されることを意味します:find2つの引数-name"*.log"(二重引用符は引数の一部です)。正確にこのように入力することも、他の同様の方法で入力することもできます。

find -name \"*.log\"
find -name "\"*.log\""
find -name '"*.'log""\"

今、あなたが書いた内容を見てみましょう。

find `echo "-name \"*.log\""`

サブシェルで実行するコマンドは次のとおりです。

echo "-name \"*.log\""

その出力は

-name "*.log"

ここでは、パラメータの二重引用符が生成されます。コマンド置換の出力がコマンドラインに挿入されると、シェル構文で解析されません。

find `echo '; rm -rf ~'`

すべてのファイルを削除するわけではありませんが、;最初の引数findrm2番目の引数、3番目の引数-rfとして渡し、ホームディレクトリ(特殊文字が含まれていないと仮定)を4番目の引数として渡します。

変数置換またはコマンド置換が二重引用符の外にある場合、変数値またはコマンド出力は次のように変換されます。

  1. コマンド置換のみ: 末尾の改行を削除します。
  2. 文字列はスペースで区切られたセグメントに分割されます。 (変数を設定して区切り文字を設定できますIFS。)この変換の結果は次のとおりです。リストひも。
  3. リストの各要素はワイルドカードパターンとして解釈されます。パターンがファイルと一致すると、その要素は一致するファイルのリストに置き換えられます。ワイルドカード)。パターンがファイルと一致しない場合、要素は保持されます。

ステップ2-name "*.log"文字列を-nameとの2つの部分に分割します"*.log"。どちらの部分もファイルと一致しないため、結果は2つの単語-nameの合計です"*.log"

あなたが望むのは、findパラメータを使用して-name実行することです*.log。ワイルドカードをオフにしてこれを行うことができます。

set -f
find `echo -name *.log`
set +f

これは強力ではありません。たとえば、スペースを含むファイル名を渡すことはできません。通常、コマンドのビットを変数に保存したり、コマンドに渡してコマンドを作成したりしないでください。現在やっていることを行う最善の方法は、実際にやりたいことが何であるかによって異なります。以下は、いくつかの一般的な提案です。

答え2

eval関数を使用すると問題が解決します。

command="find `echo \"-name \"*.log\"\"`"   response=$(eval "$command")

関連情報