この例の引用を削除する段階でbashがバックスラッシュを削除しないのはなぜですか?

この例の引用を削除する段階でbashがバックスラッシュを削除しないのはなぜですか?

バッシュから

$ va='\\abc'
$ echo $va
\\abc

割り当てでは、va='\\abc'一重引用符は値の2つのバックスラッシュを保持しますva

echoコマンドでは、bashは最初にパラメータを拡張(拡張)してから、パラメータ拡張の結果から引用符を削除します。echo $vaこれは正しいですか?引用符を削除するとバックスラッシュと引用符が削除されますが、なぜ2つのバックスラッシュが残りますか?私は結果が次のようになると予想しました。比較のため$va\\abc\abc

$ echo \\abc
\abc

Bashのマニュアルで何かを見逃しましたか?欠けている部分をご指摘いただきありがとうございます。

ありがとうございます。

ベストアンサー1

より簡単な比較で始めましょう:

$ echo '\\abc'
\\abc
$ echo \\abc
\abc

echo最初のコマンドでは、アポストロフィはすでに引用に使用されているため、パラメータの一部ではありません。 2つのバックスラッシュを含む内部のすべての文字がに​​渡されますecho

2番目のコマンドでは、最初のバックスラッシュは2番目のバックスラッシュを表します。引用に使用される内容は、主張の一部を構成しませんecho。もう1つはecho、およびabc(引用符はありませんがメタ文字ではないため重要ではありません)として渡されます。

これで、コマンドの順序について議論する準備が整いました。

$ va='\\abc'
$ echo $va
\\abc

割り当てコマンドが実行されると、アポストロフィはその間のすべてを表します。アポストロフィは割り当てられた値の一部ではありませんが、2つのバックスラッシュを含む他のすべての値の一部になります。

コマンドにはecho引用符はありません。va値を検索してパラメータリストに挿入します。 2つのバックスラッシュを含むパラメータがありますが、引用符文字を検索する解析ステップは変数拡張の前に完了するため、引用符として使用できません。

変数拡張はマクロ拡張とは異なります。結果の引数のリストは、完全なコマンドラインパーサーにフィードバックされません。いくつかの後処理(単語の分離とワイルドカード)が行われましたが、2番目の引用符の削除と変数の拡張は行われませんでした。

引数リストを作成し、利用可能なすべてのシェル機能を使用して内容全体を新しいコマンドラインに再解析する場合は、この方法を使用できますeval。 「すべてのシェル機能」が多いので、これは一般的に悪い考えです。気をつけないと悪いことが起こります。

$ va='\\abc'
$ eval echo $va
\abc

完璧ですよね?

$ va='\\abc;rm -rf $important_database'
$ eval echo $va
\abc
^C^C^C ARGH!

シェル変数の値にシェル引用構文を使用したい場合は、トラブルシューティングのための別のアプローチを考えてみてください。

おすすめ記事