先入観は怖い。
環境
- PowerShell 5.1
二重引用符文字列のクセ
"""" # 文字列 '"' 二重引用符の中で二重引用符を書くときは二つ並べます。
"$(1+1)" # 文字列 '2' 二重引用符の中で$()としたら式を中に書けます。
"$("""")" # 文字列 '' 👈 いや '"' じゃないんかい!
"`"" # 文字列 '"' 二重引用符の中で二重引用符を書くときはバッククォートでエスケープします。
"$("`"")" # 評価不可 👈 実行すらできひんのかい!
理由
式$()よりも先に""の処理が行われるから。
"$("""")" => "$("")"
"$("`"")" => "$("`")"
公式ドキュメントにはコマンドに渡される前に式が評価されると書いてある。
おそらく、文字列として処理してからコマンド(Write-Host?Set-Variable?)実行前に式が評価される。
二重引用符で囲まれた文字列は 、展開可能な文字列です 。 ドル記号 ($) の前に付いた変数名は、処理のために文字列がコマンドに渡される前に、変数の値に置き換えられます。
また、二重引用符で囲まれた文字列では、式が評価され、結果が文字列に挿入されます。
文字列に引用符文字を含める
二重引用符で囲まれた語句を二重引用符で囲みます。
対応方法
「二重引用符の中で二重引用符を使いたいときは重ねる。」が基本ルールなので、書きたい式の二重引用符を2倍すればよい。
"""" # 書きたい式
"""""""" # 二重引用符2倍
"$("""""""")" # 文字列 '"'
式を入れ子(二重引用符文字列中の式に二重引用符文字列の式)にするとさらに2倍する必要がある。
"$(""$("""""""""""""""")"")" # 文字列 '"'
ちなみにシンタックスハイライトはあてにならない。
回避策
一度変数に入れれば大丈夫。(先に式を実行する)
$a = """"
"$a" # 文字列 '"'
"$($a)" # 文字列 '"'
"$(($a = """"))" # 文字列 '' 👈 これはダメ❌
いっそのこと原点回帰で結合するのもアリ。(式を二重引用符内に書かない)
"" + """" + ""
検証データ
| 二重引用符数 | 入力 | 出力 |
""処理後 |
|---|---|---|---|
| 0 | "$()" |
空文字列 | "$()" |
| 1 | "$(")" |
❌評価不可 | "$(")" |
| 2 | "$("")" |
❌評価不可 | "$(")" |
| 3 | "$(""")" |
空文字列 | "$("")" |
| 4 | "$("""")" |
空文字列 | "$("")" |
| 5 | "$(""""")" |
❌評価不可 | "$(""")" |
| 6 | "$("""""")" |
❌評価不可 | "$(""")" |
| 7 | "$(""""""")" |
" |
"$("""")" |
| 8 | "$("""""""")" |
" |
"$("""")" |
| 9 | "$(""""""""")" |
❌評価不可 | "$(""""")" |
| 10 | "$("""""""""")" |
❌評価不可 | "$(""""")" |
| 11 | "$(""""""""""")" |
"" |
"$("""""")" |
| 12 | "$("""""""""""")" |
"" |
"$("""""")" |
| 13 | "$(""""""""""""")" |
❌評価不可 | "$(""""""")" |
| 14 | "$("""""""""""""")" |
❌評価不可 | "$(""""""")" |
| 15 | "$(""""""""""""""")" |
""" |
"$("""""""")" |
| 16 | "$("""""""""""""""")" |
""" |
"$("""""""")" |
| 17 | "$(""""""""""""""""")" |
❌評価不可 | "$(""""""""")" |
| 18 | "$("""""""""""""""""")" |
❌評価不可 | "$(""""""""")" |
| 19 | "$(""""""""""""""""""")" |
"""" |
"$("""""""""")" |
| 20 | "$("""""""""""""""""""")" |
"""" |
"$("""""""""")" |
おわり
文字列リテラルに変数や式を埋め込むことを文字列補間(string interpolation)というのだが、上記のような仕様になっている言語はほかにあるのだろうか?
追記
よく考えると、これが実行できるのが不思議だ。
"$("x")" # 文字列 'x'
文字列の始まり"から終わり"まで解析するとしたら、"$("とxと")"に分かれるように思える。
"$("のみでは評価不可なので、解析中に$()を認識していると思う。
文字列解析中に$()認識しているのに、式中の""を"にしているのは意味が分からない。
PowerShellよくわからない。どうしてこうなった。