Düzenli İfadeler / Regex
Metin / Text dosyaları ile sıklıkla uğraşıyorsanız, bir metin düzenleyicisi kullanırken, özellikle biraz büyük dosyalarda, bazı işlemlerde, normal bul değiştir işlemi ile yapılamayacağı zamanlar olabilir. Sadece Bul ve Değiştir işlemi için değil, kullandığınız bir betik dili içinde de kullanabilirsiniz, küçük bir örnek yazının devamında verilecektir.
Bu tür durumlarda, düzenli ifadeler kullanımının yardımı olacaktır.
Kelime, rakam, v.b. bulma gibi temel örnekleri, pek çok yerde kolayca bulabileceğinizi düşünerek, bir kaç örnek ile bazı ek seçenekleri anlatmaya çalışacağım.
Örnekler için, Windows üzerinde çalışan, açık kaynak bir metin düzenleyicisi olan “Notepad++” (https://notepad-plus-plus.org/) tercih ettim. Bilgisayarınıza uygulama kurmadan, ya da Windows dışında bir işletim sistemi üzerinde test etmek isterseniz;<https://regex101.com/> adresini, düzenli ifadeler ve örnek metin ile kullanabilirsiniz.
ilk örneğimizle başlayalım. Şöyle bir liste olsun:
123-456-7890
(123)456-7890
(123)-456-7890
(123-456-7890
1234567890
123 456 7890
123-456-7890
(123)456-7890
(123)-456-7890
(123-456-7890
1234567890
123 456 7890
123-456-7890
(123)456-7890
(123)-456-7890
(123-456-7890
1234567890
123 456 7890
Yukarıdaki örnekte, tüm satırlarda, ilk satırdaki gibi sayıları arasında sadece “-” tire olsun, parantez ve boşluklar olmasın istediğinizde; “bul / değiştir” ile yapılabilir diye düşünülecektir.
Parantez işaretleri ve boşlukları, “–” tire ile değiştirmek kolayken sıra, “1234567890” içeren satırlara gelince zorlanmaya başlarız.
Bu işlemi “Düzenli ifade / Regular Expression (Regex)” kullanarak yapabilirsiniz.
Kullanılacak düzenli ifadeyi açıklamaya çalışalım:
Bul/Find what: (^\d{3})(?=\d)(\d{3})
Değiştir/Replace with: $1-$2-
Bu arada, yukarıdaki örneği kullanırken, uygulamada, “Bul Değiştir” penceresinde, sol alt bölümde bulunan “Search Mode” bölümünde, “Regular expression” düğmesini seçmeyi unutmayınız!
“^\d” satır başındaki rakam, bize 3 rakamlı bir sayı gerekeceği için, 3 adet rakam olanı demek için;
“^\d{3}” sonuna süslü parantez içerisinde 3 ekleyeceğiz. Bu aşamada tüm satır başındaki 3 rakamlı sayıları bulabiliriz. Sadece bize gerekli olanları bulmak için, devamında boşluk, tire ve parantez olanları elemek için, bir ek daha yapalım ve sağ tarafında bir adet daha rakam bulananlar diyelim: “(?=\d)“
^\d{3}(?=\d)
Bu aşamada işlem yapacağımız, ilk 3 rakamı bir grup içerisine alarak, daha sonraki değiştirme işleminde kullanacağız. Bunu da parantezler içerisine alarak yapacağız: ^\d{3} —> (^\d{3})
(^\d{3})(?=\d)
Bu şekilde iken arama yaparsanız, işlem yapılacak satırları ve ilk 3 rakamı bulacaksınız.
2. grup 3’lü için yapacağımız eklemeyi tahmin edebilirsiniz:
(^\d{3})(?=\d)\d{3}
Bu 2. grubu da parantezler içerisini alıyoruz:
(^\d{3})(?=\d)(\d{3})
Değiştirme işlemi şu şekilde olacak:
$1-$2-
Bulunan birinci parantez içeriği ($1),devamında “–” ve bulunan 2. parantez içeriği ($2) ve tekrar “–“.
“Replace All” dediğinizde istenilen sonuç alınmış olacaktır.
Aynı düzenli ifadeyi, Powershell ile de kullanabilirsiniz:
Önce metin dosyası içeriğini bir değişkene aktaralım:
$tel_nolar=get-content c:\temp\tel_nolar.txt
Daha sonrada satır satır değiştirme işlemi yapalım:
foreach ($telno in $tel_nolar) {$telno -replace '(^\d{3})(?=\d)(\d{3})','$1-$2-'}
Başka bir örnekte, web adreslerine, html kod ekleyelim:
https://example.com/pic1.jpg –> <a href=“https://example.com/pic1.jpg”>https://example.com/pic1.jpg</a>
https://example.com/pic1.jpg
Https://example.com/pic2.jpg
https://example.com/pic3.jpg
Bul: (?-i)^http.+$
Değiştir: <a href=”$0″>$0</a>
Açıklamak gerekirse:
(?s-i) “-i” büyük küçük harf duyarlı olmadan yapılacağını belirtir; duyarlı yapmak isterseniz “–” ya da “(?-i)” seçeneğini kaldırabilirsiniz. Kullanıp, kullanmamanıza göre büyük “H” ile başlayan satır, bulunacak ya da bulunmayacaktır.
^http.+$ satır başında http olan, ve en az “+” 1 karakter bulunan, “$” satır sonuna kadar herşeyi bul.
Değiştir: <a href=”$0″>$0</a>
Değiştir bölümünde ise, önceki örnekte de olduğu gibi bulunan değer “$0” önüne ve ardına gerekli kodları ekleyerek değiştirme işlemi. Neden önceki örnekte “0” dan değilde “1”den başladı derseniz, aramayı parantez içerisinde kullanmadığımız için “0” ile başlıyor.
Bu örnekte, içerisinde “satır_sil” kelimeleri geçen satırları silelim.
https://example.com/pic1.jpg
https://example.com/pic2.jpg
https://example.com/satır_sil3.jpg
https://example.com/pic1.jpg
https://example.com/satır_sil.jpg
satır_sil
https://example.com/pic3.jpg
Bul: (?-is)^(?=.*satır_sil).+\R
Değiştir:
Yukarıdaki örneklerden farklı olarak, burada yapılan aramanın tek satırda gerçekleşeceği “-s” seçeneği var, “+” dan farklı olarak kullanılan “.*“, aranan kelimenin ön tarafında hiç bir karakter olmasa bile bulunmasını sağlıyor, bunu görmek için “*” ve “+” kullanarak arama yaptığınızda, tek başına “satır_sil” bulunan satırdaki durumu gözlemleyiniz.
“\R” ise satır sonu demek. Silinen satırlar boş satır olarak kalsın isterseniz bunu yerine “$” kullanabilirsiniz.
Değiştir kutucuğuna hiç bir şey yazmıyoruz.
İşlemin tersini yapmak isterseniz, aranan kelimenin önüne, soru işaretinden sonra “!” eklerseniz ve “=” kaldırırsanız, bu kelime geçen satırlar kalacak, diğerleri silinecektir.
(?-is)^(?!.*satır_sil).+\R
Yukarıdaki örneklerin bazılarında kullanılan “(?=\d)” ya da “(?=.+satır_sil)“, karakterin sağında bulunan değer demek olarak düşünebiliriz, peki sol tarafında bir şey ararsak!
Bu durumda da “<” ekleyerek kullanmak gerekir, “(?<=\d)” ya da “(?<=.+satır_sil)” gibi.
Her ikisinin kullanıldığı bir örnek yapalım.
[Köşeli parantez içerisinde örnek metin]
[Köşeli parantez içerisinde metin]
[Köşeli parantez örnek metin]
Köşeli parantezler içerisindeki metni bulmaya çalışalım.
(?s)(?<=\[).+?(?=\])
Bu düzenli ifade de, yukarıdaki açıklamalardan farklı olarak, köşeli parantezler önünde “\” işareti var; bunun nedeni, köşeli parantezlerin, düzenli ifadeler içinde farklı bir amaçla kullanılmasından kaynaklanması. Aynı şeyi “.”, “?”, “)”, “=” ve pek çok diğer karakter için de söyleyebiliriz; örneğin, nokta için arama yapmak istersek “\.” kullanmalıyız. İkinci fark olarak, “(?=\])” önünde, ek bir “?” bulunması. Bunun da nedeni, ilk bulunan “\]” durması için; aksi takdirde, son köşeli paranteze kadar bulma işlemi yapılacaktır. Bunu ekleyerek ya da çıkararak test edebilirsiniz.
Yukarıdaki 2 örneği birleştirmeye çalışalım:
[
Köşeli parantez içerisinde test örnek metin
ve kelimeye göre arama
][
Köşeli parantez içerisinde örnek metin
][
Köşeli parantez içerisinde test örnek metin
ve kelimeye göre arama
]
“Test” kelimesi geçen ve köşeli parantez arasında kalan satırları bulalım, “[” bir önemi yok, her hangi bir şey de olabilir:
(?-s)(.*\R){1}.*test(?s).+?\]
Yukarıda değinildiği için çok kısaca açıklamak gerekirse; “.*test” kelimesi ve öncesi kelimeler, “(?-s)(.*\R){1}.” 1 üst satır son olarak da “(?s).+?\]” paranteze kadar olan bölüm.
Peki, “[” bir önemi olmadığı için, 2. “]” parantezin de olmadığını düşünerek, bulunduğu satırdan itibaren 3 satır devamını seçmek gerekirse, “(?s).+?\]” yerine “(.+\R){3}” kullanmak yeterli olacaktır.
(?-s)(.*\R){1}.*test(.+\R){3}
Pratik olması amacıyla bir başka örnek daha yapalım. Etki alanından, bir kullanıcı hesabının üye olduğu grup isimlerini bulalım.
Bu örnekteki “get-aduser” PowerShell komutunun çalışması için, örneği yapacağınız istemcinizde RSAT (Remote server admin. tools ) aracı yüklü olması ya da “ActiveDirectory” PS modülünü yüklemeniz gerekmektedir. Araçları yüklemek için, internet erişimi olduğu var sayılan istemcinizde, yönetici yetkisi ile bir PowerShell konsol açınız ve aşağıdaki komutu veriniz:
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
Önce uzun yoldan, bir etki alanı kullanıcısının üye olduğu grupları alalım. Bu işlemi düzenli ifadeler ile yapmak biraz kulağı tersten göstermek gibi 🙂 , Yazının sonunda daha kısa, tek satır PS komut verilecektir.
Powershell konsolda:
get-aduser ad_hesap -Properties MemberOf | format-table MemberOf
MemberOf
——–
{CN=ConfigMgr Remote Control Users,CN=Users,DC=etki_alani,DC=com,DC=tr, CN=BT,OU=FW,DC=etki_alani,DC=c…
Biraz daha okunur olması için:get-aduser ad_hesap -Properties MemberOf | select-object MemberOf -ExpandProperty MemberOf
CN=ConfigMgr Remote Control Users,CN=Users,DC=etki_alani,DC=com,DC=tr
CN=Protected Users,CN=Users,DC=etki_alani,DC=com,DC=tr
CN=Domain Admins,CN=Users,DC=etki_alani,DC=com,DC=tr
Bunların içerisinde sadece grup isimlerini bulalım:get-aduser ad_hesap -Properties MemberOf | select-object MemberOf -ExpandProperty MemberOf | Select-String -AllMatches '(?<=^CN=).*?(?=,)'
CN=ConfigMgr Remote Control Users,CN=Users,DC=etki_alani,DC=com,DC=tr
CN=Protected Users,CN=Users,DC=etki_alani,DC=com,DC=tr
CN=Domain Admins,CN=Users,DC=etki_alani,DC=com,DC=tr
‘(?<=^CN=).*?(?=,)‘ düzenli ifadesini açıklamak gerekirse “.*” aradığımız grup ismi, “(?<=^CN=)” sol tarafında “^CN=” ile başlayan, “?(?=,)” sağ tarafında “=,” bulunan demek. Parantez önündeki soru işareti, devam eden “=,” leri bulmaması için.
Bulunan değerleri görmeye çalışalım:get-aduser ad_hesap -Properties MemberOf | select-object MemberOf -ExpandProperty MemberOf | Select-String -AllMatches '(?<=^CN=).*?(?=,)' | Select-Object -ExpandProperty Matches
Groups : {0}
Success : True
Name : 0
Captures : {0}
Index : 3
Length : 30
Value : ConfigMgr Remote Control Users
ValueSpan :…
son olarak da bulunan değerleri listeleyelim:get-aduser ad_hesap -Properties MemberOf | Select-Object MemberOf -ExpandProperty MemberOf | Select-String -AllMatches '(?<=^CN=).*?(?=,)' | Select-Object -ExpandProperty Matches | format-table Value
Value
—–
ConfigMgr
Remote Control Users
Protected Users
Domain Admins
Yukarıda örnek pratik olması amacıyla verilmiştir, amacınız sadece etki alanı hesabının grupları ise, regex olmadan, aşağıdaki PS komutunu da kullanabilirsiniz 🙂
(Get-ADUser -Identity ad_hesap -Properties MemberOf).MemberOf | ForEach-Object -Process {($_ -split ',')[0].Substring(3)} | Sort-Object
İyi çalışmalar.
Eline sağlık.