PowerShell ve Regex ile Seçkin Ayrıştırma
Geçen gün arkadaşım Gladys Kravitz ile Active Directory hakkında sohbet ediyorum ve kuruluş birimi adlarının seçkin bir addan ayrıştırılması konusunda hazırlıksız bir açıklama yapıyor. Bir yandan bu, Active Directory cmdlet'lerinden uygun bir ayırt edici ad varsayıldığında oldukça basit bir iştir. Gerçekten yapmanız gereken tek şey dizeyi bölmek.
$ou = "OU=Foo,OU=Top,DC=Company,DC=pri"
$ou.split(",")[0]Kod virgül üzerinde bölünüyor ve dizideki ilk öğeyi seçiyor.
Ama bir alternatif olduğunu düşündüm. Peki ya sadece üst düzey kuruluş biriminin adını, yani Foo'yu istersem? Doğal olarak normal ifadelere yöneldim.
Açgözlü Olmayın
Bir dizi test ayırt edici ad değeri oluşturarak başladım.
$DN = @("OU=Foo,OU=Top,DC=Company,DC=pri",
"OU=Foo123,OU=FooBar,DC=Company,DC=pri",
"ou=Foo,ou=Top,dc=Company,dc=pri",
"OU=Gladys Kravitz Monitors,OU=Top,DC=Company,DC=pri",
"OU=A723-Test,OU=Top,OU=Middle,DC=Company,DC=pri",
"OU=JEA_Operators,DC=Company,DC=Pri",
"CN=Users,DC=Company,DC=pri",
"CN=ArtD,OU=IT,DC=Company,DC=Pri",
"cn=johnd,ou=sales,dc=company,dc=pri",
"CN=SamS,OU=This,OU=That,DC=Company,DC=Pri",
"OU=Domain Controllers,DC=Company,DC=Pri")
Yakından bakarsanız, verilerin nasıl görüneceğini her zaman garanti edemeyebileceğim için çeşitli formlar kullandığımı göreceksiniz. Ayrıca bu alıştırmaya, en iyi kuruluş birimi adını seçkin bir kuruluş birimi adından alma perspektifinden başlıyorum. Başarısız olması gerektiğini bildiğim test değerlerini ekledim. Bir normal ifade modeliyle geliştirme yaparken başarısız olması gerektiğini bildiğiniz verilerle test yapmak önemlidir.
Bu verilerle şu düzenli ifade modeliyle başladım:
[regex]$rx = "^(ou|OU)=.*(?=,)"Desen şöyle diyor: "Satır çizgisinin (^) başlangıcına sabitleyin ve "ou" veya (|) "OU" ve ardından=dizesini arayın. Daha sonra ileriye baktığınızda virgül (?=,) göreceğiniz herhangi bir karakter (.*). Dizideki ilk öğeyi deneyelim.
Bu çoğunlukla işe yaradı. Sorun, desenin mümkün olan her dizeyle eşleşmesidir. Başka bir deyişle, düzenli ifade modeli açgözlüydü. Çoğu zaman bu bir sorun değildir. Ancak burada ilk OU eşleşmesinden sonra normal ifade modelinin durmasını istiyorum.
[regex]$rx = "^(ou|OU)=.*?(?=,)"Temel fark “?” .”*”dan sonra eklenir. Bu, desenin ilk eşleşmeden sonra durmasına neden olur.
Artık isim dizisini işleyebilirim.
Eşleşmeyen dizeler için boşluklar aldığımdan istediğim kadar temiz değil. Bu daha iyi olabilir.
Artık değeri yalnızca bir eşleşme varsa alıyorum. Ama bunu daha da ileriye taşımak istiyorum.
Adlandırılmış Yakalamalar
Foo ve Foo123 gibi ilk kuruluş biriminin adını almak istediğime karar verdim. Bunu yapmak için adlandırılmış bir yakalama kullanacağım. İşte revize edilmiş normal ifade modelim.
[regex]$rx = "^(ou|OU)=(?<OUName>.*?(?=,))"Temel fark, şimdi desenin parantez içine alınmış son kısmında eşleşen herhangi bir şey için bir ad, OUName tanımlıyor olmamdır. Açgözlü olmayan desenin önüne “?
İşte sadece adlandırılmış yakalamayı elde etmek için bir komut dosyası yazma numarası.
Bu, dizimi işleyebileceğim anlamına geliyor:
$dn | Where-Object { $rx.IsMatch($_) } | ForEach-Object { $rx.Match($_).groups["OUName"].Value }Bir sonraki adımım normalde bu kodu temel alan bir işlev oluşturmak olacaktır. Ama daha bitirmedim.
En İyi Kuruluş Birimi Adını Alın
Kullanıcılar ve gruplar için ayırt edici adlara ne dersiniz? Üst düzey kuruluş biriminin adını ayrıştırabilmek istiyorum. Bununla test edeceğim.
$art = "CN=ArtD,OU=IT,DC=Company,DC=Pri"İşin zor kısmı, dizenin CN veya OU ile başlayabilmesidir. İşte normal ifade modelimin başka bir versiyonu daha.
[regex]$rx = "^(((CN=.*?))?)(ou|OU)=(?<OUName>.*?(?=,))"Bu kalıpla, başlangıçta
“CN=birşey” ile başlayabilecek bir şey arıyorum.
^(((CN=.*?))?)Desen açgözlü olmayan bir eşleşme kullanıyor. Genel kalıp isteğe bağlıdır. Yani mevcut olabilir. Format if “(
İyi görünüyor. Dizi “cn” ile başlamış olsa da başarısız olur.
Bu, PowerShell'de normal ifadelerle çalışırken olası bir tuzaktır ve neden $DN test veri kümeme çeşitli büyük/küçük harfler ekledim. Büyük/küçük harf sorunlarından kaçınmanın daha iyi bir yolu regex nesnesini bu şekilde tanımlamaktır.
$rx = [System.Text.RegularExpressions.Regex]::new("^(((CN=.*?))?)OU=(?<OUName>.*?(?=,))","IgnoreCase")Artık dizenin OU, ou veya ou kullanması önemli değil. Hepsi eşleşecek.
Ve test verilerimi kullanmak artık kullanıcı ve grup adlarını işliyor.
Harika. Bu kodu temel alarak, ayırt edici bir adı işleyecek ve ilk veya üst kuruluş birimi adını sağlayacak bir işlev oluşturacağım.
Function Get-TopOUName {
[cmdletbinding()]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[alias("dn")]
[string]$DistinguishedName
)
Begin {
Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
#ignore case
$rx = [System.Text.RegularExpressions.Regex]::new("^(((CN=.*?))?)OU=(?<OUName>.*?(?=,))","IgnoreCase")
} #begin
Process {
Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Processing $DistinguishedName"
If ($rx.IsMatch($DistinguishedName) ) {
$rx.Match($DistinguishedName).groups["OUName"].Value
}
} #process
End {
Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
} #end
}Yakından bakarsanız CN=Users,DC=Company,DC=pri'nin bir sonuç üretmediğini göreceksiniz, bu da modelimin çalıştığı anlamına geliyor. Bunu Active Directory ile test edelim.
Get-ADUser -filter * | Select-Object Name,SamAccountName,
@{Name="OU";Expression={Get-TopOUName $_.distinguishedname}},distinguishednameBu ilk birkaç hesap bir kuruluş biriminde olmadığından sonuç beklendiği gibi olur. Ama artık kullanabileceğim bir aracım var.
Daha fazla bilgi edin
Kalıplarıma veya kodlarıma Active Directory ile çalışmak için pratik bir ihtiyacınız olmayabilir. Ama umarım soruna nasıl yaklaştığımı ve birkaç düzenli ifade kavramını nasıl örneklediğimi öğreneceksiniz. Düzenli ifadeler hakkında daha fazla bilgi edinmek istiyorsanız konuyla ilgili tam bir Çoğul Görüş kursum var.
Basit dize bölme işlemi işe yararsa, elbette kolay yolu seçin. Ancak bazen biraz daha karmaşık bir şeye ihtiyacınız olabilir ve bence düzenli ifadelerin zarif bir çözüm olduğunu göreceksiniz.














