LoginSignup
0
1

More than 5 years have passed since last update.

Powershellのコードの字句解析

Posted at

Powershellのコードは簡単に字句解析ができることを知ったので、その方法のメモ。

使うもの

PSParser.Tokenize Method (System.Management.Automation) | Microsoft Docs

上記のメソッドにコードを渡せば、解析結果を返してくれます。

使用例

PowerShell自身で実行してみる場合のコードです。

# 字句解析したいスクリプト文字列
[string]$code = {Get-ChildItem -LiteralPath $PSHOME -Filter *.exe}.ToString()
<# $code =>
Get-ChildItem -LiteralPath $PSHOME -Filter *.exe
#>

# 解析エラーを入れる変数。中身は`Tokenize`内で設定されるため$nullでOK
[Collections.ObjectModel.Collection[Management.Automation.PSParseError]]$parseErrors = $null

# トークン化
[Management.Automation.PSToken[]]$tokens = 
    [Management.Automation.PSParser]::Tokenize($code, [ref]$parseErrors)

# 表示用に整形
$tokens | Format-Table -AutoSize

結果

Content Type Start Length StartLine StartColumn EndLine EndColumn
Get-ChildItem Command 0 13 1 1 1 14
-LiteralPath CommandParameter 14 12 1 15 1 27
PSHOME Variable 27 7 1 28 1 35
-Filter CommandParameter 35 7 1 36 1 43
*.exe CommandArgument 43 5 1 44 1 49

各トークン毎に、中身・種類・文字列中どの位置なのか、が取得できているのが分かります。

補足

基本は書いてある通りですが、いくつか気になった点があったのでその補足です。

構文エラーも無視して解析される

[Management.Automation.PSParser]::Tokenizeは構文エラーがあった場合も、最後まで解析が行われ結果が返ります。

構文エラーを確認したい場合は、第2引数(上記のコードだと$parseErrors)の個数や中身をチェックします。

ただし、上記のコードではスクリプトブロックをToString()しているため、構文エラーがある場合はスクリプトブロック生成段階でエラーが起きます。

空白はトークンではない

当たり前といえば当たり前の話ではありますが、スペースなどはトークンとして認識されません。

ただし、改行に関してはNewLineというTypeで表現されます。

変数の$Contentに含まれない

PowerShellの変数は$から始まりますが、先頭の$は結果のContentに含まれません。

$も含めた範囲を取得したい場合は、以下のように元の文字列からSubStringで切り出す必要があります。

$tokens |
    ForEach-Object -Process {
        $code.Substring($_.Start, $_.Length)
    }
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1