先入観は怖い。
環境
- 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よくわからない。どうしてこうなった。