PowerShell ve Normal İfadelerle Adları Yakalama


PowerShell'i öğrenmeye ve benimsemeye devam ettikçe, sonunda düzenli ifadelerle tanışacaksınız. Umarım birçoğunuz zaten bazı temel bilgilere sahipsinizdir. değilse, başlamanız gereken ilk yer, about_regular_expressions adlı yardım konusunu okumaktır. Bu makalede, size yakalamalar adı verilen gelişmiş bir düzenli ifade konusunu tanıtacağım. İtiraf edeyim ki bu konuyu ilk öğrendiğimde başımı döndürdü. Ama umarım atlıkarıncayı yavaşlatabilirim.

Bunun gibi bir dizeyle başlayalım.

$t = "2019-06-21 17:12:31Z : 172.16.1.123 [ Begin process data ]"

Bu bir günlük dosyasında bulunabilecek bir şeydir. .PowerShell'in gücü nesnelerle çalışma yeteneğinden geldiğinden, günlük dosyasını bir nesne koleksiyonuna dönüştürmek daha kolay olabilir.

Desenlerle Başlayın

Bunun işe yaraması ve normal ifadeleri kullanabilmeniz için verilerinizin nasıl görüneceğini bilmeniz, tutarlı ve öngörülebilir olması gerekir. Bu örnekte, bir tarihsaat dizesi, bir IPv4 adresi ve ardından parantezlerin içinde bir mesajım var. İlk adım, bu farklı öğelerle eşleşen bir düzenli ifade modeli oluşturmaktır. Tarihsaat ile başlayalım.

$t -match "\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}Z"

Desen diyor ki, tam olarak 4 rakamla başlayan bir şey bulun. \d bir rakam anlamına gelir ve {4} tam olarak 4 rakam anlamına gelir. Sonra bir tire ve ardından tam olarak 2 rakam (\d{2}), başka bir tire ve 2 rakam gelir. Bu bana tarihi verir. Ama biraz daha fazlası var. Alanı (\s) yakalamam gerekiyor ve sonra artık tanımanız gereken zamanla eşleşecek bir modelim var. Sonu gerçek bir Z'dir

Gördüğünüz gibi bu tam olarak istediğim şeyle eşleşiyor. Bu arada, genellikle yazabileceğiniz birden fazla desen vardır. Basit ve net kalıplara bağlı kalmaya çalışıyorum. Düzenli ifadeler yeterince şifreli olabilir!

Daha sonra IP adresini eşleştirmem gerekiyor.

$t -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"

Kalıpta en az 1 rakamla başlayıp 3'ten fazla olmayacak şekilde (\d{1,3}) ve ardından gerçek bir noktanın geldiği belirtiliyor. (\.). Nokta, herhangi bir anlama gelen özel bir düzenli ifade karakteridir. \, PowerShell'e gerçek bir nokta aramasını söyleyen kaçış karakteridir. Bu model kalan sekizlilerde tekrarlanır.

Bu kalıp, adresi doğrulamaz, yalnızca bir IP adresine görünmesini sağlar. Daha kısıtlayıcı modeller var ama daha fazla karmaşıklık eklemek istemedim. Benim durumumda adresin geçerli olacağını biliyorum.

Sonuncusu köşeli parantezler arasındaki metindir.

$t -match "\[.*\]"

Parantez özel bir düzenli ifade karakteri olduğundan ondan kaçmam gerekiyor. Daha sonra herhangi bir karakterin (.) birden fazla örneğini (*) eşleştirmeyi istiyorum.

İsimleri Tanımlayın

Eşleşen desenleriniz olduğunda bunları bir adla tanımlayabilirsiniz. Genel düzen şuna benzer:

(?<capture-name>Your-Pattern)

Parantezler anahtardır. Datetime modelim adlandırılmış bir yakalama olarak tanımlanabilir:

(?<date>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}Z)

İşte metnin tamamını baştan sona açıklayan bir kalıp.

[regex]$rx = '(?<date>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}Z)\s:\s(?<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s\[\s(?<status>.*)\]'

Son deseni parantezleri içermeyecek şekilde değiştirdim. Kullanabileceğim başka gelişmiş düzenli ifade teknikleri de var ama bunları basit tuttum. Unutulmaması gereken önemli nokta, $rx'i özel bir nesne türü olarak tanımladığımdır. Bu regex nesnesi, -match operatörünü kullanmaktan çok daha fazlasını yapmamı sağlıyor. Bu durumda eşleşme aramak için kullanabilirim.

Bu iyi. Peki isimler nasıl devreye giriyor?

PowerShell'de Adlandırılmış Yakalamaları Kullanma

Maçta Gruplar özelliğini görebilirsiniz. Adlandırılmış yakalamaların bulunabileceği yer burasıdır.

PowerShell'i kullanarak eşleşen ilk grubu atlayarak yalnızca adlandırılmış yakalamaları elde etmek kolaydır.

Bu neredeyse bir nesneye benziyor! gerçek bir nesne yaratmak çok daha fazlasını gerektirmez.

$m.groups | Select-Object -Skip 1 | foreach-object -begin { $h = @{}  } -process {
    $h.Add($_.name,$_.value.trim())
} -end {
    [pscustomobject]$h
}

Ancak tarihin bir dize yerine bir tarihsaat nesnesi olması daha iyi olurdu. Adlandırılmış yakalamalarınızın sırasını bildiğinizi varsayan bir alternatifi burada bulabilirsiniz.

$o = [pscustomobject]@{
    Date = $m.groups[1].value -as [datetime]
    IPAddress = $m.groups[2].value -as [ipaddress]
    Status = $m.groups[3].value 
}

Gördüğünüz gibi bu bir nesne.

Bu kodla, günlük dosyasının her satırını işleyecek ve özel bir nesne oluşturacak bir komut dosyası yazabilirim. Bu, verilerle ne yapmam gerekiyorsa filtrelemeyi, sıralamayı veya yapmayı çok daha kolay hale getiriyor.

ConvertFrom-Text

Veya daha kolay bir yola ne dersiniz? Artık adlandırılmış yakalamaları kullanarak normal ifade modelini nasıl oluşturacağınızı bildiğinize göre, PowerShell Galerisinden yükleyebileceğiniz PSScriptTools modülümdeki ConvertFrom-Text komutunu kullanabilirsiniz. Bu komutla herhangi bir metin çıktısını PowerShell nesnelerine dönüştürmek için kod oluşturabilirsiniz.

$c = "(?<Protocol>\w{3})\s+(?<LocalIP>(\d{1,3}\.){3}\d{1,3}):(?<LocalPort>\d+)\s+(?<ForeignIP>.*):(?<ForeignPort>\d+)\s+(?<State>\w+)?"
netstat -an | select -skip 4 | convertfrom-text $c | where-object {$_.LocalIP -ne '0.0.0.0'} | format-table -autosize

En azından bazı temel düzenli ifade becerilerine sahip olduğunuzda, kendinizi bunu sıklıkla kullanırken bulacaksınız. Ve her yeni dilde olduğu gibi, onu ne kadar çok kullanırsanız o kadar akıcı olursunuz.

İlgili makaleler