PowerShell AST ile Takma Adları Keşfetme
PowerShell komut dosyalarını ve işlevlerini dosyalara dönüştürmeyle ilgili son gönderilerimden birkaçının kodunu içeren yeni bir PowerShell modülü üzerinde çalışıyorum. Hatta modüle eklediğim komutları kullanarak modülü oluşturmak için bir komut dosyası hazırladım, bunu bir meta komut dosyası olarak düşünün. Bunu başka bir gün ele alacağım. Bu betiği yazma sürecinde dosyalarda tanımlanan işlevler için takma adlar da belirlemek istediğimi fark ettim.
Özellikle fonksiyonun kendisinde tanımlanan takma adları bulmak istedim.
Function Get-Foo {
[cmdletbinding()]
[alias("gf")]
Param (...)
...Komut dosyası dosyasını basitçe nokta kaynaklı olarak bulabilir ve ardından takma adları arayabilirdim. Ancak nokta kaynak kullanımının bir seçenek olduğunu varsaymak istemedim. Bunun yerine dosyayı AST ile ayrıştırmaya geri döndüm.
Maalesef AST'de özellikle komut takma adlarını alan hiçbir şey bulamadım. Bir şeyi kaçırıyorsam lütfen bana bildirin. Bunun yerine, işlev gövdesini ayrıştırmak için düzenli ifadelere güvendim. Önceki yazılarda gösterdiğim kodu kullanarak dosyalardaki işlevleri bulmak artık çok kolay.
Bu yalnızca bir kavram kanıtıdır. Hala takma adları çıkarmam gerekiyor. İleriye ve geriye bakmayı kullanan bir düzenli ifade modeli kullanacağım.
[regex]$rx = "(?<=alias\().*(?=\)\])"İfade, .* kullanan herhangi bir şeyle eşleşmeyi söylüyor; burada önce gelen metin (arkasına bakan) "takma ad(" ve sonraki metin (önden bakan) ")]" olur. Parantezler ve köşeli parantezler normal ifade karakterleridir, dolayısıyla onlardan eğik çizgiyle kaçmam gerekiyor. Daha sonra eşleşmeyi temizleyebilir ve takma adları alabilirim.
İşte PowerShell işlevim.
Function Get-FunctionAlias {
[cmdletbinding()]
[alias("gfal", "ga")]
[outputType("string")]
Param(
[Parameter(Position = 0, Mandatory, HelpMessage = "Specify the .ps1 or .psm1 file with defined functions.")]
[ValidateScript( {
If (Test-Path $_ ) {
$True
}
Else {
Throw "Can't validate that $_ exists. Please verify and try again."
$False
}
})]
[ValidateScript( {
If ($_ -match "\.ps(m)?1$") {
$True
}
Else {
Throw "The path must be to a .ps1 or .psm1 file."
$False
}
})]
[string]$Path
)
New-Variable astTokens -Force
New-Variable astErr -Force
$Path = Convert-Path -Path $path
[regex]$rx = "(?<=alias\().*(?=\)\])"
Write-Verbose "Parsing $path for functions."
$AST = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$astTokens, [ref]$astErr)
#parse out functions using the AST
$functions = $ast.FindAll( { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)
if ($functions.count -gt 0) {
foreach ($f in $functions) {
if ($rx.IsMatch($f.body)) {
[pscustomobject]@{
Name = $f.name
#remove quotes from the alias names and join as a comma-separated array
Alias = ($rx.matches($f.body).value -replace """|'", "") -split ","
}
}
}
}
}
Fonksiyonu kendi takma adlarını keşfetmek için kullanalım.
PowerShell betik dosyamın tanımlanmış takma adlara sahip iki işlevi var. Yeni bir PowerShell modülünün derlemesini yazarken bu bilgiyi kullanabilirim. Gündemin bir sonraki konusu bu konu.
Bu arada, umarım buna bir göz atarsınız ve onu nasıl kullanabileceğinizi veya neyin daha da yararlı olabileceğini bana bildirirsiniz.
Güncelleme
Bunu yayınladıktan kısa bir süre sonra Przemysław Kłys, takma ad bilgilerini çıkarmak için PowerShell AST'yi kullanan bazı kodları paylaşma nezaketini gösterdi. Ben her zaman düzenli ifadeleri kullanmanın bir yolunu aramama rağmen onun yaklaşımı çok daha zarif. İşte fonksiyonun revize edilmiş bir versiyonu. Çıkış değişmez.

