PowerShell Düzenli İfadeler (PowerShell Regex)
PowerShell Regex Kullanımı, PowerShell Regular Expression Kullanımı, PowerShell Düzenli İfadeler
PowerShell Düzenli İfadeler (PowerShell Regex)
Windows PowerShell, Microsoft tarafından temel olarak sistem yönetimi için tasarlanmış bir programlama dilidir. PowerShell .NET Framework üzerine inşa edildiğinden, .NET üzerinde mükemmeleştirilmiş olan düzenli ifadeler desteği, PowerShell programcıları tarafından da kullanılabilir.
Düzenli ifadeler (Regex – Regular Expression) metni eşleştirir ve ayrıştırır. Düzenli ifade dili, kalıpları tanımlamak için güçlü bir kısayoldur. Powershell, düzenli ifadeleri çeşitli şekillerde kullanır. Bazen bu komutların kullandığını unutmak kolaydır çünkü kullanılan dil ve regex çok sıkı entegre hale gelmiştir. Bu komutların bazıları zaten kullanıyor ve farkında olunamayabilir.
PowerShell düzenli ifadeler için sözdizimi ve dili öğretmek bu makalenin kapsamı dışındadır. Sadece PowerShell’e odaklanmak için, şimdilik ihtiyaç duyulacak şeyler ele alınacaktır. Düzenli ifade örnekleri bilerek çok basit olacaktır. İleride ihtiyaç duyuldukça bu konuya tekrar tekrar girilecektir.
PowerShell Düzenli İfadeler (Regex) İçin Hızlı Başlangıç
Kesin eşleşmeler için desenlerde normal sayılar ve karakterler kullanılabilir. Neyin eşleşmesi gerektiği tam olarak bilindiğinde bu işe yarayacaktır. Bazen herhangi bir rakam veya harfin eşleşmesi gereken bir desene ihtiyaç olabilir. İşte bu şekilde örneklerde kullanılabilecek bazı temel desenler:
\d Tek haneli rakam [0-9] \w Alfa nümerik [a-zA-Z0-9_] \s Boşluk karakteri . Satırsonu hariç herhangi bir karakter () Alt İfade \ Bir sonraki ifade için kaçış karakteridir
Buna göre \d\d\d\d\d\d\d\d\d\d\d
paterni Türkiye Cumhuriyeti kimlik numarasıyla eşleşecektir. Elbette algoritma 11 haneli bir rakam ile sınırlı değildir. Aynı modeli temsil etmenin daha iyi ve daha kompakt yolları vardır. Ancak bu örnek şimdilik yukarıdaki paternlerin anlaşılması için açıklayıcı olacaktır.
PowerShell Düzenli İfadeler (Regex) İçin Kaynakları
Çalışmalarınız için doğru kalıpları bulmanıza yardımcı olacak bazı düzenli ifade kaynakları aşağıda görülebilir.
Online düzenli ifade hesaplayıcıları:
Dökümantasyon ve eğitim:
Select-String
Bu cmdlet, metin deseni ile dosyaları veya dizinleri aramak için mükemmeldir.
Get-ChildItem -Path $aramaFolder | Select Name | Select-String -Pattern 'Error'
Bu örnekte “$aramaFolder” dizininde bulunan tüm dosyalar içinde isminde “Error” kelimesini içeren dosyaları arar. “Pattern” parametresi düzenli bir ifade içindir ve bu durumda “Error” sözcüğü düzenli ifade şeklindedir. İçinde “Error” kelimesi olan herhangi bir dosyayı bulur.
Get-ChildItem -Path $aramaFolder | Select Name | Select-String -Pattern "\d\d\d\d\d\d\d\d\d\d\d"
Yukarıdaki ifade “$aramaFolder” dizininde isimlendirmesi “T.C. Kimlik Numarası” gibi görünen dosyalar için arama yapar.
-match
-match operatörü düzenli bir ifade alır ve patern eşleşirse $true değerini döndürür.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $message = 'Bu klasörde çok fazla error log dosyası var.' $message -match 'error' "12345678901" -match "\d\d\d\d\d\d\d\d\d\d\d" True True PS C:\Users\ahmet\Desktop\Aktif Dizin>
Eğer bir diziye bir eşleme uygulanırsa, desenle eşleşen tüm öğelerin bir listesi alınır.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $data = @( "Anlamsız genel cümleler" "Benim T.C. Kimlik Numaram 12345678901" "Diğer anlamsız genel cümleler" "Arkadaşın T.C. Kimlik Numarası 92345678905" ) $data -match '\d\d\d\d\d\d\d\d\d\d\d' Benim T.C. Kimlik Numaram 12345678901 Arkadaşın T.C. Kimlik Numarası 92345678905 PS C:\Users\ahmet\Desktop\Aktif Dizin>
Varyasyonları:
- -imatch, büyük/küçük harfe duyarlı olmayan şekilde çalışır.
- -cmatch, işlemi büyük/küçük harfe duyarlı hale getirir.
- -notmatch, eşleşme olmadığında true değerini döndürür.
- ‘i‘ ve ‘c‘, tüm karşılaştırma operatörleri için kullanılabilir.
-like
“-like” komutu, regex kullanmaması dışında “-match” gibidir. Daha basit bir joker desen kullanır, burada “?” herhangi bir karakter ve “*” birden fazla bilinmeyen karakterdir.
$message -like '*error*'
Önemli bir fark, joker karakterler eklenmediği sürece -like komutunun tam eşleşmeyi beklemesidir. Bu nedenle, daha büyük bir veride bir desen aranıyorsa, her iki uca da ‘*error*’ şeklinde joker karakterler eklenmesi gereklidir.
Bazen aslında ihtiyaç olan tek şey temel bir joker karakterdir ve burada -like devreye girer.
Bu operatör -ilike, -clike, -notlike varyantlarına sahiptir.
String.Contains()
Tüm yapılmak istenilen bir ifadenin bir alt ifadesi olup olmadığını test edilmesiyse, “string.contains($altIfade)” yaklaşımı kullanılabilir.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $message = 'Bu klasörde çok fazla error log dosyası var.' $message.Contains("error") True PS C:\Users\ahmet\Desktop\Aktif Dizin>
“string.contains()” büyük/küçük harfe duyarlıdır. Bu operatör, bu alt ifade bulma senaryoları için diğer operatörleri kullanmaktan daha iyi performans gösterir.
-replace
-replace komutu, desen eşleşmesi için düzenli ifade kullanır.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $message = "Hey! Benim adım Ahmet." $message -replace 'Ahmet.','Attila değil!' $message = "Benim T.C. Kimlik Numaram 12345678901" $message -replace '\d\d\d\d\d\d\d\d\d\d\d', '92345678905' Hey! Benim adım Attila değil! Benim T.C. Kimlik Numaram 92345678905 PS C:\Users\ahmet\Desktop\Aktif Dizin>
Bu komutun diğer varyantları -creplace ve -ireplace şeklindedir.
String.Replace ()
.Net “String.Replace($pattern, $replacement)” operatörü düzenli ifade kullanmaz. “-replace” operatöründen daha iyi performans gösterir.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $message = "Hey! Benim adım Ahmet." $message.Replace('Ahmet.','Attila değil!') Hey! Benim adım Attila değil! PS C:\Users\ahmet\Desktop\Aktif Dizin>
Tüm diğer ifade operatörleri gibi bu operatörde büyük/küçük harfe duyarlıdır.
-split
Bu komut genellikle düzenli ifade kullanan komutlar arasında göz ardı edilir.
PS C:\Users\ahmet\Desktop\Aktif Dizin> '05 Şubat 2020' -split ' ' 05 Şubat 2020 PS C:\Users\ahmet\Desktop\Aktif Dizin>
Bu operatörle her seferinde değişik şekillerde başka bir şey anlamına gelen başka bir karakter düzenli ifade olarak kullanılmaya çalışılacaktır. Ancak bazen bu çok beklenmedik sonuçlara yol açacaktır. Boşluk yerinde bir nokta olsaydı, bir sürü boş satır dönerdi.
PS C:\Users\ahmet\Desktop\Aktif Dizin> '05.Şubat.2020' -split '.' PS C:\Users\ahmet\Desktop\Aktif Dizin>
Bunun sebebi düzenli ifadelerde ‘.’ işareti herhangi bir karakterle eşleşir ve bu durumda her karakterle eşleşir. Her karaktere ayrılır ve bize 14 boş değer verir.
PS C:\Users\ahmet\Desktop\Aktif Dizin> ('05.Şubat.2020' -split '.').Count 14
Yukarıdaki nedenle hangi komutların regex kullandığını hatırlamak önemlidir.
-isplit ve -csplit bu komutun diğer varyantlarıdır.
String.Split()
String.Replace() komutunda olduğu gibi String.Split() operatörü de regex kullanmaz. Bir karaktere (yada alt ifadeye) bölmek için daha iyi performansı vardır ve aynı sonuçlar döndürülür.
Switch
Varsayılan olarak “switch” ifadesi tam olarak eşleşir. Ancak bunun yerine düzenli ifade eşleşmelerini kullanmak için “-regex” seçeneği vardır.
$message = 'Benim T.C. Kimlik Numaram 12345678901' switch -regex ($message) { '\d\d\d\d\d\d\d\d\d\d\d' { Write-Warning 'Bu mesaj T.C. Kimlik Numarası içeriyor.' } '\d\d\d\d-\d\d\d\d-\d\d\d\d-\d\d\d\d' { Write-Warning 'Bu mesaj kredi kartı numarası içeriyor.' } }
PowerShell Düzenli İfadeler ValidatePattern
Gelişmiş bir PowerShell fonksiyon oluştururken, parametrenize bir [ValidatePattern()] ekleyebilirsiniz. Bu, gelen değerin beklediğiniz kalıba sahip olup olmadığını doğrular.
Function Get-Data { [cmdletbinding()] param( [ValidatePattern('\d\d\d\d\d\d\d\d\d\d\d')] [string] $TCKN ) # ... # }
Bu örnek kullanıcıdan bir TCKN ister ve girişte doğrulama yapar. Bu geçerli değilse kullanıcıya bir hata mesajı verecektir. Varsayılan olarak iyi bir hata mesajı vermemektedir.
PS C:\Users\ahmet\Desktop\Aktif Dizin> Function Get-Data { [cmdletbinding()] param( [ValidatePattern('\d\d\d\d\d\d\d\d\d\d\d')] [string] $TCKN ) # ... # } Get-Data -TCKN "ahmet" Get-Data : Cannot validate argument on parameter 'TCKN'. The argument "ahmet" does not match the "\d\d\d\d\d\d\d\d\d\d\d" pattern. Supply an argument that matches "\d\d\d\d\d\d\d\d\d\d\d" and try the command again. At line:13 char:16 + Get-Data -TCKN "ahmet" + ~~~~~~~ + CategoryInfo : InvalidData: (:) [Get-Data], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Get-Data PS C:\Users\ahmet\Desktop\Aktif Dizin>
PowerShell Düzenli İfadeler ValidateScript
Bunun bir yolu, bunun yerine özel bir hata mesajı verebilen [ValidateScript({…})] kullanmaktır.
Function Get-Data { [CmdletBinding()] param ( [ValidateScript({ if( $_ -match '\d\d\d\d\d\d\d\d\d\d\d') { $true } else { throw 'Lütfen Geçerli Bir TC Kimlik Numarası Veriniz (örn. 12345678901)' } })] [string] $TCKN ) } Get-Data -TCKN "ahmet"
Şimdi belirlenen hata mesajı alınabilir.
Get-Data -TCKN "ahmet" Get-Data : Cannot validate argument on parameter 'TCKN'. Lütfen Geçerli Bir TC Kimlik Numarası Veriniz (örn. 12345678901)
PowerShell Core Validate ErrorMessage
Doğrulama betiğinin sadece belirtilen bir hata mesajını vermek için kullanılması biraz çirkin. PowerShell Core da yeni bir özellik, ErrorMessage parametresini kullanarak ValiatePattern için özel bir hata mesajı belirlenebilmesidir. ErrorMessage’ı nasıl belirlenebileceği aşağıda açıklanmıştır:
[ValidatePattern('\d\d\d\d\d\d\d\d\d\d\d', ErrorMessage = 'Lütfen Geçerli Bir TC Kimlik Numarası Veriniz (örn. 12345678901)')]
Bir değer eşleşmediğinde, kullanıcı aşağıdaki hatayla karşılaşır.
Get-Data : Cannot validate argument on parameter 'TCKN'. Lütfen Geçerli Bir TC Kimlik Numarası Veriniz (örn. 12345678901)
Bu harika yeni bir özellik olsa da, PowerShell’in eski sürümleri için kodu geçersiz kılar. Windows Powershell’de aynı kod çalıştırılırsa, aşağıdaki hata iletisi alınır:
Property 'ErrorMessage' cannot be found for type 'System.Management.Automation.ValidatePatternAttribute'.
Değişkenler üzerinde doğrulayıcılar (Validators on variables)
Doğrulayıcılar çoğunlukla gelişmiş bir fonksiyonun parçası olarak düşünülebilir. Ancak gerçek şu ki, değişken için bile geçerli olup ve gelişmiş bir fonksiyonun dışında kullanılabilirler.
[ValidatePattern('\d\d\d\d\d\d\d\d\d\d\d')] [string]$TCKN = '12345678901' $TCKN = "Bilemedim :)" The variable cannot be validated because the value Bilemedim :) is not a valid value for the TCKN variable.
$Matches
-Match operatörü kullanıldığında, $Matches adlı otomatik bir değişken eşleşmenin sonuçlarını içerir. Düzenli ifadede alt ifadeleri varsa, bu alt ifadelerin eşleşmeleri de listelenir.
$message = "Benim T.C. Kimlik Numaram 12345678901." $message -match 'Benim T.C. Kimlik Numaram (\d\d\d\d\d\d\d\d\d\d\d)\.' $Matches[0] $Matches[1]
Benim T.C. Kimlik Numaram 12345678901. 12345678901
PowerShell Adlandırılmış Eşleşmeler (Named Matches)
PowerShell adlandırılmış eşleşmeler, çoğu insanın bilmediği ancak çok iyi düşünülmüş özelliklerden biridir. İsimlendirilmiş düzenli ifade eşleşmesi kullanıyorsanız, o eşleşmeye isimlerine göre erişebilirsiniz.
$message = 'Benim adım Ahmet ve T.C. Kimlik Numaram 12345678901.' if($message -match 'Benim adım (?<Ad>.+) ve T.C. Kimlik Numaram (?<TCKN>\d\d\d\d\d\d\d\d\d\d\d)\.') { $Matches.Ad $Matches.TCKN }
Yukarıdaki örnekte görülen, (?<Ad>.+) adlandırılmış bir alt ifadedir. Bu değer daha sonra $Matches.Ad özelliğine yerleştirilir. TCKN için de aynı şey geçerlidir.
.Net Regex
PowerShell dilinden, .Net regex nesnesine tam erişim bulunur. Çoğu yukarıdaki işlevsellik kapsamındadır. Özel seçeneklere ihtiyaç duyulduğunda, daha gelişmiş düzenli ifade gerekiyorsa kullanılabilir.
[regex]::new($pattern) | Get-Member
Tüm .Net regex yöntemleri büyük/küçük harfe duyarlıdır.
Escape(Kaçış) Regex
Regex ortak semboller ve sözdizimleri içeren karmaşık bir dildir. Bir desen yerine değişmez bir değerle eşleşmesi istenebilecek zamanlar olabilir. [Regex]::Escape() kullanıldığında tüm düzenli ifade sözdiziminden kaçacaktır.
Örnek olarak (312)441-3141 telefon numarası ele alınırsa, bu ifade belirgin olmayan regex sözdizimi içerir.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $message = $message = 'Bana (312)441-3141 telefon numarasından ulaşabilirsin.' $message -match '(312)441-3141' False
Bunun belirli bir telefon numarasıyla eşleştiği düşünülebilir. Ancak eşleşeceği şey 123456-7890’dır. Yani düzenli ifadenin beklendiği yerde, bunun yerine normal bir string vs. ifade kullandığınızda, beklenmedik sonuçlar elde edersiniz. [Regex]::Escape() yöntemi bu sorunu çözer.
PS C:\Users\ahmet\Desktop\Aktif Dizin> $message = $message = 'Bana (312)441-3141 telefon numarasından ulaşabilirsin.' $message -match [regex]::Escape('(312)441-3141') True
Her Satırda Birden Fazla Eşleşme
-Match operatörü satır başına yalnızca bir kez eşleşir. Böylece $matches değişkeni yalnızca bu ilk eşleşmeyi içerir. Satır içinde birden fazla eşleşme olduğu durumlarda söz konusu olabilir.
-AllMatches
Select-String -AllMatches parametresiyle bunun için destek sunar. Bu durumda, döndürülen nesne her eşleşme için bir Matches özelliği içerir.
$data = 'Eğlenceler 21-02-2020 tarihinde başlayıp 23-02-2020 tarihinde sona erecek.' $tarih = '\d\d-\d\d-\d\d\d\d' $sonuc = $data | Select-String $tarih -AllMatches $sonuc.Matches.Value 21-02-2020 23-02-2020
Regex Matches()
$data = 'Eğlenceler 21-02-2020 tarihinde başlayıp 23-02-2020 tarihinde sona erecek.' $tarih = [Regex]::new('\d\d-\d\d-\d\d\d\d') $eslesme = $tarih.Matches($data) $eslesme.Value 21-02-2020 23-02-2020
PowerShell Düzenli İfadeler (PowerShell Regex)
Makalesini okuduğunuz için teşekkür ederiz. Aşağıdaki formu kullanarak soru ve önerilerinizi bize iletebilirsiniz.