
バッシュから
$ 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!
シェル変数の値にシェル引用構文を使用したい場合は、トラブルシューティングのための別のアプローチを考えてみてください。
答え2
Bashのマニュアルで何かを見逃しましたか?
はい。マニュアルから:
\
前の拡張の後、上記の拡張のいずれかで生成されなかった '' ' ' ' ' ' ' 文字の引用されていないすべてのエントリが'
削除されます。"
ここで、「前拡張」と「上位拡張」とは、パラメータ(変数)拡張、命令置換などを意味します。
答え3
答えは簡単です。一行です。
echo $va
削除する必要がある引用符は含まれていません。
これは40年以上シェルの定義でした。 Bourne Shellは1976年にAT&Tで初めて登場しました。
注:この文脈で「参照」とは、1970年代の8ビットオープン文字を意味します。これがシェルの内部引用形式です。
Bourne Shellが8ビット文字をサポートするように再設計されたため、この形式の内部引用は1980年代半ばに内部文字列で引用された文字の前にバックスラッシュに置き換えられました。
現在、Bourne Shellは次のように動作します。
一重引用符で書かれた文字列はバックスラッシュで置き換えられます。たとえば、これは 'abc' が \a\b\c に置き換えられることを意味します。
明示的な型のバックスラッシュを含む文字列は内部的に保持されます。
二重引用符で囲まれた文字列は二重引用符を保持するため、「abc」は内部的に「abc」のままです。
引数拡張を実行すると、シェルはすべての種類の引用符付き文字列(上記の3つの形式を参照)を、文字の前に単一のバックスラッシュが先行する形式に置き換えます。これは、「引用符の削除」を実行すると削除されます。
ところで: 変数拡張:
abc=123
完成した
command "$abc"
明らかにする
command \1\2\3
見積もりの削除を完了する前。
command $abc
明らかにする
command 123
見積もりの削除を完了する前。