bash変数展開が引用符を保持するのはなぜですか?


12
> echo "hi"
hi
> VAR='echo "hi"'
> $VAR
"hi"

上記のコマンドの出力が異なるのはなぜですか?

単一引用符でも同様のことが起こります。

> VAR="echo 'hi'"
> $VAR
> 'hi'

6
実行可能スクリプトスニペットを変数に埋め込む習慣を身に付けないでください。これは、傾向にある最高の状態でトリッキーevalあなたは非常に慎重に踏む必要があります潜在的なセキュリティホールの地雷原である
jw013

@ jw013良い点と素晴らしい記事。「変数はデータを保持し、関数はコードを保持します」という引用が好きです。最初のリンクからですが、私の使用法では、関数(この場合はat)に与えられるデータコードです。提供されるコードを整理/収集するより安全な方法に関するヒントはありatますか?
コリークライン

atsh入力として構文を取ります。したがって、入力を生成することatsh、任意の入力から有効で適切に引用された構文を生成することを意味します。達成しようとしていることについてもう少し詳しく説明できれば、本当に役立ちます。
jw013

申し訳ありませんが、あまり詳細に注意をそらしたくはありませんでしたが、私がやっていることはそれほど複雑ではありません、IMO。「時間」と「メッセージ」をとるスクリプトを作成しています。次にat、指定された「時間」の間at実行され、コマンドの実行を指示しますdzen2dzen2stdinから「メッセージ」を取得し、他の静的パラメーターも使用します。困難なのは、ユーザーからの「メッセージ」パラメーターをdzen2コマンドにパイプする必要があることですが、実際dzen2には自分で実行しているのではなく、実行atするように指示しています。
コリークライン

回答:


16

追加の引用符のペアは、追加の評価ステップによってのみ消費されます。たとえば、次のように強制されevalます。

bash-4.2$ VAR='echo "hi"'

bash-4.2$ $VAR
"hi"

bash-4.2$ eval $VAR
hi

ただし、一般に、パラメーター付きのコマンドを1つの文字列に入れるのは悪い考えです。代わりに配列を使用します。

bash-4.2$ VAR=(echo "hi")

bash-4.2$ "${VAR[@]}"
hi

1
引用符の評価方法が異なることに注意することも重要です。二重引用符( ")囲まれた文字列の評価、単一引用符が( ')リテラルとして文字列を印刷することができ例:。"$(ls)"そして'$(ls)'これは、引用符は、元の質問の例に表示された理由である。。
ジョセフ・カーン

配列も問題の原因です。コードは関数に、データは変数に属します。提示する例は、配列の分割で引用符が削除されるためにのみ機能します。Aは、printf '<%s> ' "${VAR[@]}"引用符がすでに削除されていることが表示されます。VAR=(echo \"hi\")実際に引用符があるようにVARを設定すると、同じ問題が再び表示され、$ ${VAR[@]}印刷されます"hi"

9

引用の削除は、元の入力語でのみ行われ、展開の結果では行わません。拡張された変数の一部である引用符は変更されません。


2

少し前に戻ると、変数置換が引用符を絶対に保持する必要がある理由がわかります。

Unix / Linux / BSDシェルの引用符のポイントは、そうでなければ複数の文字列として解析される文字列の断片をまとめることです。デフォルトでは、シェルはトークン区切り文字として空白を使用するため、スペースを含む文字列(「one two three」など)が引用またはエスケープされない場合、「one」、「two」、および「three」の3つの文字列として解析されます。

プログラマーが、ある変数の値を補間した文字列が必要な場合:

VAR=two
STRING="one $VAR three"

シェルは引用符を絶対に削除しないでください。スペースを含む文字列は3つの小さな文字列として解析されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.