この記事では以下について説明します。
- PowerShellが解釈するシングルクォート、ダブルクォート、そのエスケープ
- コマンド等が解釈するワイルドカードとそのエスケープ
- コマンド等が解釈する正規表現とそのエスケープ
2021/07/26 更新:記事を全体的に書き直しました。
PowerShellによる文字列の解釈
PowerShellでは、シングルクォートとダブルクォートのどちらで囲うかによって処理が違います。
参考:about_Quoting_Rules - PowerShell | Microsoft Docs
シングルクォート
シングルクォートで囲った文字列は、そのままの文字列として扱われます。
唯一の例外はシングルクォートで、シングルクォートはシングルクォート自身でエスケープします。
'$i is 5' # Output: $i is 5
'don''t' # Output: don't
ダブルクォート
ダブルクォートで囲った文字列は、変数、式、後述するエスケープシーケンスが置換されます。変数はドル記号 $
を前に付けます。式はドル記号と丸括弧 $( )
内に記述します。
$i = 5
"$i is 5" # Output: 5 is 5
"${i}th" # Output: 5th
"$(2+3) is 5" # Output: 5 is 5
特殊文字のエスケープ
特殊文字をエスケープするには、バッククォート `
を前に付けます。
ダブルクォートはダブルクォート自身でエスケープすることもできます。
$i = 5
"`$i is $i" # Output: $i is 5
"`$(2+3) is $(2+3)" # Output: $(2+3) is 5
"``" # Output: `
"`"" # Output: "
"""" # Output: "
エスケープシーケンス
ダブルクォートで囲った文字列では、以下のエスケープシーケンスなどが使用できます。
シーケンス | 説明
- | -
`n | 改行
`t | 水平タブ
`u{x} | ユニコード文字(※バージョン5では利用不可)
"Column1`t`tColumn2`t`tColumn3" # Output: Column1 Column2 Column3
"line`nbreak"
<# Output:
line
break
#>
PowerShellで使用できるすべてのエスケープシーケンスとその使い方については、以下の参考リンクをご参照ください。
参考:about_Special_Characters - PowerShell | Microsoft Docs
なお、エスケープシーケンスにならない普通の文字の前にバッククォートを付けた場合は、単にバッククォートが消えます。
"he`llo`,` world`!" # Output: hello, world!
オブジェクトのプロパティの展開
変数(オブジェクト)のプロパティを展開するには、式 $( )
の記法が使えます。
$obj = [PSCustomObject]@{property="hello"}
"property is $($obj.property)" # Output: property is hello
コマンド等による文字列の解釈
一部のコマンドや演算子などでは、ワイルドカードや正規表現がサポートされています。それらの記法を説明します。
ワイルドカード
ワイルドカードは、一部のコマンドおよび -like
演算子でサポートされています。どのコマンドがワイルドカードをサポートしているかは一概に言えませんが、-Path
や -Name
の引数であれば基本的にワイルドカードが使えるようです。
ワイルドカードの説明は以下のとおりです。
ワイルドカード | 説明 | 記述例 | 一致例
- | - | - | -
- | 0文字以上の任意の文字 |
a*
| A, ag, Apple
? | 任意の1文字 |?n
| An, in
[ ] | 範囲内の1文字 |[a-c]
| a, b, c
[ ] | いずれか1文字 |[bcl]ook
| book, cook, look
参考:
- about_Wildcards - PowerShell | Microsoft Docs
- Supporting Wildcard Characters in Cmdlet Parameters - PowerShell | Microsoft Docs
ワイルドカードのエスケープ
ワイルドカードをエスケープするには、バッククォート `
を前に付けます。このとき、バッククォートがPowerShellに解釈されないように、シングルクォートで文字列を囲ったほうがよいです。
'[test] hello' -like '[test]*' # Output: False (※右側の [ ] はワイルドカード扱い)
'[test] hello' -like '`[test`]*' # Output: True
'`test hello' -like '`test*' # Output: False (※右の `t は t に変換されて評価される模様)
'`test hello' -like '``test*' # Output: True
ダブルクォートで文字列を囲うと、最初にPowerShellで解釈されるので、以下のようにバッククォートをエスケープしておく必要が出てきます。
'[test] hello' -like "[test]*" # Output: False
'[test] hello' -like "`[test`]*" # Output: False
'[test] hello' -like "``[test``]*" # Output: True
'`test hello' -like "`test*" # Output: False
'`test hello' -like "``test*" # Output: False
'`test hello' -like "```test*" # Output: False
'`test hello' -like "````test*" # Output: True
'`test hello' -like "`````test*" # Output: False
'`test hello' -like "``````test*" # Output: True
※下段の ```test
は前から順番に ``
`t
でそれぞれ解釈されます。`t
は、-like
演算子にとってはエスケープシーケンスでも何でもないため、単に t
になります。
-Path
の引数でワイルドカードが必要ない場合は、代わりに -LiteralPath
が使えます。
Get-ChildItem -Path '[test].txt' # t.txt, e.txt, s.txt がヒット
Get-ChildItem -LiteralPath '[test].txt' # [test].txt がヒット
-Path
の引数でエスケープする必要がある場合は、シングルクォートで囲ったとしてもバッククォートが2個 ``
必要となるようです(※Get-ChildItem
コマンドで確認。他のコマンドでは不明。おそらく内部的に2回エスケープ処理されているのだと思われます)。
# 名前が[test]から始まるファイルを見つける
Get-ChildItem -Path '[test]*' # NG
Get-ChildItem -Path '`[test`]*' # NG
Get-ChildItem -Path '``[test``]*' # OK
正規表現
正規表現は以下のコマンド、文、演算子で利用できます。
Select-String
-
switch
文 -
-match
-replace
-split
演算子
これらはデフォルトでは大文字と小文字を区別しません。区別する場合は、それぞれ以下のようにします。
Select-String -CaseSensitive
switch -CaseSensitive
-
-cmatch
-creplace
-csplit
ここで、正規表現の記法を一部紹介します。他の記法や具体例は、以下の参考リンクをご参照ください。
記号 | 説明
- | -
. | 任意の一文字(ワイルドカード)
- | 直前の文字の0回以上の繰り返し
- | 直前の文字の1回以上の繰り返し
? | 直前の文字が0回か1回
{n} | 直前の文字のn回の繰り返し
{n,} | 直前の文字のn回以上の繰り返し
{n,m} | 直前の文字のn回からm回の繰り返し
^ | 文字列の先頭、行頭
$ | 文字列の末尾、行末
[a-z] | 範囲内の1文字
[abc] | いずれか1文字
\w | 英数字とアンダースコアの1文字
\d | 数字の1文字
\s | スペース
\t | タブ
\r | キャリッジリターン
\n | 改行
参考:
- about_Regular_Expressions - PowerShell | Microsoft Docs
- Regular Expression Language - Quick Reference | Microsoft Docs
正規表現のエスケープ
正規表現内でスケープするにはバックスラッシュ \
を使用します。例えば、ピリオドを表すには \.
とします。
-replace
演算子でのキャプチャと置換
<入力> -replace <正規表現>,<置換文字列>
では、「正規表現」内の ( )
で囲った部分をキャプチャし、「置換文字列」内で順番に $1
$2
… と記述して変数のように使うことができます(PowerShellの変数ではないことに注意)。
'Japan Tokyo' -replace '(\w+) (\w+)','$2, $1' # Output: Tokyo, Japan
「置換文字列」内でドル記号をエスケープするには $$
とします(※「正規表現」内では \$
でエスケープします)。
'500 USD' -replace '(\d+) USD','$$$1' # Output: $500
ここでも、ダブルクォートで囲うとPowerShellの変数や式などが展開されることに注意します。
$i = 5
'<h> hours' -replace '<h>',"$i" # Output: 5 hours
「置換文字列」内でタブなどの特殊文字を使うにはダブルクォートで囲って `t
などを使います(※「正規表現」側では \t
などを使います)。
'a,b' -replace ',',"`t" # Output: a b
あとがき
最近PowerShellの勉強を始めた筆者です。
Get-Alias ?
を実行したらよく分からない実行結果が出てきたので、それをきっかけにいろいろ調べた結果、この記事ができました。
以下をご覧ください。
Get-Alias ? # 「1文字のエイリアス」がヒット
Get-Alias '?' # 「1文字のエイリアス」がヒット
Get-Alias '`?' # 「?」がヒット
Get-Alias "?" # 「1文字のエイリアス」がヒット
Get-Alias "`?" # 「1文字のエイリアス」がヒット
Get-Alias "``?" # 「?」がヒット
この記事を最後まで読んでくださった皆さんは、上の実行結果がなぜこのようになるのか、ある程度理解できるようになったことと思います。私もいろいろ調べたおかげで理解できたのでよかったです。
Get-Alias ?
の事情について詳しく知りたい場合は、こちらの記事(PowerShell Deep Dive: Understanding Get-Alias, wildcards, escape characters, quoting rules, literal vs. non-literal paths, and the timing of string evaluation – Poshoholic)をご参照ください。