29.11.2021

Windows Terminal ve oh-my-posh

Daha önce Powershell komut satırını özelleştirme ile ilgili yazmıştım. Ama bu sefer daha gelişmiş bir terminal arayüzü için özellikle Scott Hanselman'ın videolarında ve blog'unda bahsettiği oh-my-posh (oh-my-bash benzeri) gibi bileşenleri ile ilgili yazacağım.

oh-my-posh'un kurmanın 2 yolu var:

1. PowershellGet:

Yönetici haklarıyla açılmış bir powershell penceresinde

PS> Install-Module oh-my-posh

yazmak. Bunun sonucunda önce PSGallery'ye güvenmek isteyip istemediğimizi soracak. 

2. Windows Paket Yöneticisi (winget)

Komut satırından

PS> winget install JanDeDobbeleer.OhMyPosh

yazmak. Burada install'dan sonra gelen tam adı (aslında ID) yazabilmek için  önce içinde 

oh-my-posh yazan paketleri aratmak isteyebiliriz.

PS> winget search ohmyposh

Name       Id                      Version Match           Source
-----------------------------------------------------------------
Oh My Posh JanDeDobbeleer.OhMyPosh 6.18.1  Tag: oh-my-posh winget

Kurulumu tamamladık. Öncelikle kullanabileceğimiz temaları görelim.

PS> Import-Module oh-my-posh

PS> Get-PoshThemes

Burada listelenen temalardan birini seçtikten sonra bunu profil dosyamıza ekleyip kalıcı yapabiliriz. Ben jblab_2021 temasıyla ilerleyeceğim.

PS> notepad $PROFILE

ile profil dosyamızı açıp içine şu satırları ekleyelim (dosya yoksa yeni bir dosya yaratmamız gerekir).

Import-Module oh-my-posh

Set-PoshPrompt jblab_2021

Aslında bu aşamadan önce yapılması gerekirdi ama yapılmazsa ne farkediyor diye görmek için sonra bıraktım. Varsayılan olarak kullanılan font aileleri sembol olarak kullanılan bazı karakterleri desteklemiyor. Bu amaçla özel bir font ailesi yüklememiz gerek. Scott Hanselman'ın videosunda gördüğüm nerdfonts.com sitesi güzel. Ben de bu siteden Caskaydia Cove Nerd Font ailesini yükledim. Zip dosyasını indirdikten sonra içindekileri Windows klasörünün içindeki Fonts klasörüne kopyalamak gerekecek. Ardından bu kullandığımız terminalde bu fontları görmek için ayarlardan tercih edilen font ailesi seçimini yapmamız gerek. Terminal derken yeni Windows Terminal'i de kuralım.

PS> winget install Microsoft.WindowsTerminal

Bu aşamadan sonra promptumuz tamamlandı. Eğer git kullanıyorsanız ve komut satırından git işlemleri için görsel destek arıyorsak ek olarak posh-git modülünü kurabiliriz.

PS> Install-Module posh-git

Git dışında başka faydalı özelliklerden biri Spotify'da çalan şarkı bilgisni komut satırı prompt'unda görmek olabilir. Bunu eklemek için cinnamon, jtracey93 veya night-owl gibi temalardan birini seçmek ya da mevcut temamızı Export-PoshTheme ile temanızı bir dosyaya yazmak ve sonra bu dosyı düzenleyerek içine bir Spotify segmenti eklememiz gerek.

Yeni farkettiğim başka bir faydalı özellik de PSReadline için geçmişe dayalı tahmin özelliği. Bunu etkinleştirmek için

PS> Set-PSReadlineOption -PredictionSource History

Yapmak yeterli. Bunu elbette her açılan terminal penceresinde olmasını istiyorsak $Profile içine kaydetmeliyiz. PSReadline sürüm 2.1.0 veya üzeri gerekli. Şu an beta sürümünde bazı yeni özellikler de var, güncellemeleri kaçırmamak gerek.

21.09.2021

linux rm komudu ve parametreleri

Komut satırı, genel olarak grafik arayüze kıyasla daha fazla seçenek sunuyor. Ama tüm komutları ve tüm parametrelerini hatırlamak da ayrıca bir çaba gerektiriyor; ya da en azından bir blog sayfasına yazıp gerektiğinde bakmayı falan.

Silme amacıyla kullanılan rm komutunun bir sürü kullanışlı parametresi var. En basitinden başlayalım.

Bir dosyayı silmek için

# rm dosya

Sorunsuz silinirse hiçbir bilgi vermez. Ama var olmayan bir dosyayı silmeyi denersek

rm: cannot remove 'deneme2.txt': No such file or directory

veya yazma koruması olan bir dosyayı silmeye çalışırsak da 

rm: remove write-protected regular file 'filename'?

gibi bir hata mesajı alabiliriz.

Her türlü bize sildiği dosyanın bilgisini versin istersek -v (verbose) parametresini kullanabiliriz.

# rm -v dosya

Ya da yazma korumasına sahip dosyayı da silmesini istersek -f (force) parametresini kullanabiliriz.

# rm -f dosya

Birden fazla dosyayı silmek için ard arda isimleri yazabilir

# rm dosya1 dosya2 dosya3.txt dosya4.jpg dosya5.zip

ya da wildcard karakterleri kullanabiliriz.

# rm dosya*.txt

Bir klasörü içindekilerle birlikte silmek istersek -r (recursively) parametresini

# rm -r  klasor

ve boş bir klasörü silmek için de -d (directory) parametresini kullanabiliriz.

# rm -d bosklasor

Farkedilebileceği gibi silerken "Emin misini?" gibi bir soru sormaz, rm komudu. Eğer sormasını istersek -i parametresini kullanabiliriz.

# rm -i dosya1 dosya2

Birden fazla dosyayı silerken dosya sayısı kadar değil, sadece 1 kez sorsun yeter diyorsak -I (büyük i) parametresi işimizi görür.

# rm -I dosya*.txt

Hiç başıma gelmemişti ama tire karakteriyle başlayan dosyaları silmek için iki yol önerilmiş[1]. Biri 2 kez tire parametresi:

# rm -- -dosya

İkinci yol da -iv parametresi ile tam yol belirtmek:

# rm -iv /home/metin/-dosya

[1] https://bytexd.com/rm-command-in-linux/

20.08.2021

Fedora ve Ubuntu'da unutulan parolayı sıfırlamak

Parolalar unutulur. Unutulduğunda sıfırlanmaları gerekir. Bu her işletim sistemi için geçerli.

Ubuntu ile başlayalım. Açılıştaki Grub menüsünden recovery seçeneği ile başlamak gerek. Recovery genelde Advanced Options altında kurulu her çekirdek (kernel) sürümü için ayrı ayrı verilmiştir. En yenisi ile başlayabiliriz. Bu adımdan sonra bir nonktada aşağıdaki gibi bir ekran ile karşılaşacağız.

 
Burada kırmızı ile belirtilen root seçimi ile ilerleyeceğiz. Bir sonrak aşamada 

Press Enter for maintenance
(or press Control-D to continue):

mesajı bizi karşılayacak. Enter'a basıp root ile giriş yapacağımız terminali açalım. Control-D sadece normal açılışa devam etmek için. Bizim istediğimiz bu değil.

Artık burada 

# passwd <kullanıcı_adi>

komutu ile parolamızı değiştirebiliriz. Yetki hatası alırsak

# mount -o remount,rw /

komutu ile diskimizi yazma modunda mount ederek passwd komutunu tekrar deneyebiliriz.

Eğer kullanıcı adımızı da unuttuysak

ls /home

komutu ile sisteme oturum açmış kullanıcıların ev klasörleri arasından seçim yapabiliriz. Şifre değiştirme işlemi tamamlandıktan sonra

# reboot

komutu ile sistemi tekrar başlatabiliriz.

Fedora için işler biraz daha farklı. Açılışta grub menüsündeyken Fedora'nın satırında "e"ye basarak düzenleme moduna geçip aşağıdaki ekranda kırmızı ile işaretlediğim satırı

load_video
set gfxpayload=keep
insmod gzio
linux ($root)/vlinux-5.13.9-200.fc34.x86_64 root=/dev/mapper/fedora_localhost\
--live-root ro resume=/dev/mapper/fedora_localhost--live-swap rd.lvm.lv=fedora\
_localhost-live/root rd.lvm.lv=fedora_localhost-live/swap rhgb quiet
initrd ($root)/initramfs-5.13.9-200.fc34.x86_64.img

Şununla değiştirmemiz gerek:

rd.break enforcing=0

Değiştirdikten sonra bu ayalarla sistemi başlatmak için Ctrl+X'e basalım. Sistem yine grafik arayüz olmadan tek kullanıcılı modda açılacak. Burada yine Ubuntu'daki gibi

Press Enter for maintenance
(or press Control-D to continue):

Ekranı gelecek. Enter'la devam edelim. Fedora'da root partition'ı yazma modunda tekrar mount etmek şifreyi değiştirmek için:

# mount -o remount,rw /sysroot, 
# chroot /sysroot
# passwd <username>

yapmak gerek. İşler bittiğinde 2 kez exit yazıp enter'a basarak tekrar başlatacağız.

Açılışta Fedora SELinux koruması bize /etc/shadow dosyasının SELinux etiketlerinin yanlış olduğuyla ilgili uyarılar verebilir. Bir komut satırı açıp şunları yazmamız gerekecek:

# sudo restorecon -v /etc/shadow

Bunun öncesinde

# ls -Z /etc/shadow

system_u:object_r:unlabeled_t:s0 /etc/shadow

olan SELinux etkiketinin sonrasında

# ls -Z /etc/shadow

system_u:object_r:shadow_t:s0 /etc/shadow

olarak değiştirildiğini görebiliriz. Son olarak

# sudo set enforcing 1

ile SELinux'u tekrar etkinleştirebiliriz.

Server üzerinde bir süreç sonlanınca eposta göndersin

Temel olarak Windows olay günlüğüne belli bir yeni olay düştüğünde eposta göndermek veya başka bir komut çalıştırmak mümkün. Ben de bir sürecin sonlanması durumunda eposta göndereceğim. Sürecin sonlanmasını da Sysinternals arası Sysmon ile denetleyeceğim. İstenmesi durumunda:

  • Bir sürecin başlaması veya sonlanması
  • Bir dosyanın oluşturulması veya silinmesi
  • Kayıt defterinde bir değer oluşturulması veya silinmesi
  • Belirli bir IP adresine/porta ağ bağlantısı yapılması

gibi durumlarda istenen hareket yapılabilir.

Öncelikle sysmon'u istenen sürecin sonlanması durumu için bir yapılandıralım. İlk iş, sistemde var olan bir sysmon yapılandırması bulunuyor mu, bakalım:

> sysmon64 -c

Bu satırdan sonra "Sysmon is not installed on this computer" yazdıysa sistemde var olan bir yapılandırma yoktur ve sıfırdan başlayabiliriz. Eğer bir yapılandırma varsa onu bozmadan üzerine yapılandırma yapmak gerek. -c anahtarıyla gösterilen xml dosyasını bulup yapılandırmamızı bunun üzerine yapmamız gerekecek. Bu konumuz dışında. Eğer varolan bir yapılandırma varsa ve sıfırlamak istiyorsak

> sysmon64 -c --

ile sıfırlayabiliriz.

Tekrar başa dönelim; "Sysmon is not installed on this computer" yazdıysa sistemde hiç sysmon hizmet sürücüsü kurulmamış demektir. Bu durumda sysmon'u -i anahtarıyla çalıştırarak hizmet sürücüsünü kurabiliriz. Ben 64-bitlik sürümünü kullanacağım. Ayrıca ilk çalıştırmada son kullanıcı lisans anlaşmasını (EULA) da kabul etmem gerek (-accepeula).

> sysmon64 -accepteula -i process_end.xml

Terminalimiz Powershell ise dosyaları belirtirken önlerine tam adlarını (aynı klasördeysek de .\process_end.xml şeklinde) yazmamız gerek. Tab tamamlaması bu durumda çok işe yarar.

process_end.xml dosyası oluşturmadan sadece -i anahtarını kullanarak başlarsak varsayılan ayarlar geçerli olur ve takibini yapmak istediğimiz olay sadece bizim ilgilendiğimiz uygulama için değil, sistemdeki tüm uygulamalar için yaratılır, ve çok fazla eposta almaya başlarız. Bunun için böyle bir xml dosyası ile hedefimizi daraltmamız gerekecek.

Gelelim xml dosyasının oluşturulmasına. Şu anda bende sürüm 13.22 yüklü. Bu sürümde şema sürümü de 4.70. Bunu da xml dosyamızda belirtmemiz gerekecek. 13.22 ile birlikte 4.70 veya öncesi şema sürümleri de kullanılabilir ama sürümler arası fark bazen beklenmeyen sonuçlar verdiği için (RuleGrup'ların mantıksal operatörleri varsayılan işleme biçimi gibi) ne yaptığımızı bildiğimizden emin olmamız gerek. XML dosyasındaki ilk satır şema versiyonu:

<Sysmon schemaversion="4.7">

Bu satırdan sonra hash algoritmamızı belirtelim. Olay günlüğüne çalıştırılan her uygulamanın hash'i de hesaplanıp yazılacak.

<HashAlgorithms>sha256</HashAlgorithms>

Sadece 1 ölçütüm (süreç sonlanma) olduğu için daha fazla karıştırmadan bununla ilgili process terminate tag'ını girelim

<EventFiltering>

<ProcessTerminate onmatch="include">

Takip ettiğimiz sürecin hangi özelliği ile ilgileniyoruz? Örnek olarak sistemdeki process explorer'ı takip edelim (procexp64.exe)

<Image condition="end with">procexp64.exe</Image>

Nihai olarak açık taglarımızı kapatlım:

</ProcessTerminate>

</EventFiltering>

</Sysmon>

Her process explorer'ın sonlanmasında "Microsoft-Windows-Sysmon/Operational" EWT olay günlüğüne 5 numaralı olay kayıtları düşer. Görmek için olay günlüğünde Uygulama ve Hizmet Logları (Applications and Services Logs)>Microsoft>Windows>Sysmon>Operational altına bakmak gerek. Gelelim bu olay kayıtları için bir hareket oluşturmaya. Olay günlüğüne bir tane 5 numaralı olay düştükten sonra olay görüntüleyicisi penceresinin sağ kısmında "Bu olaya göreve ekle (Attach Task to this Event)"e tıklayarak işleme devam edebiliriz. Uygulama çalıştırmanın dışındaki diğer seçenekler (eposta göndermek ve bir mesaj görüntülemek) artık terk edilmiş hareketler. Biz eposta gönderebilmek için bir powershell script'i kullanacağız. Şöyle bir script işimizi görür:

$EmailFrom = "gonderen@mailadresi.com"
$EmailTo = "alici@alantaraf.com"
$Subject ="procexp sonlandı"
$Body = "Bekledigimiz Process Explorer'ın sonlanması şu an gerçekleşti."
$SMTPServer = "smtpsunucu.mailadresi.com"$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)

Bu dosyanın ilk 5 satırı sırasıyla gönderenin eposta adresi, alıcının eposta adresi, eposta mesajının konusu, mesajın içeriği ve eposta sunucumuz şeklinde. Bunları uygun şekilde değiştirmek gerek.

Bu scriptin C:\Users\metin\Belgeler\eposta_gonder.ps1 gibi bir konumuna kaydedildiğini varsayalım.

En son olaya görev ekleme aşamasında kalmıştık. Bu pencerede3 kutu var. Birincisi çalıştırılacak program. Buraya powershell.exe'nin konumunu yazmamız gerek. Bu çoğu durumda 

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

şeklindedir. Argumanlar için yapmamız gereken birinci iş geçici olarak Execution Policy'yi devre dışı bırakmamız ve scriptimizi bir -File anahtarı ile göstermemiz. Hepsi birlikte şöyle olabilir:

-ExecutionPolicy Bypass -File C:\Users\metin\Belgeler\eposta_gonder.ps1

Üçüncü kutu sadece çalışacak script bulunduğu klasörle ilgili bir dosya işlemi yapacaksa gerekli. Bizimki gerekmeyeceği için boş bırakabiliriz. Boş kalmasın diyenler C:\Users\metin\Belgeler\ gibi birşey yazabilir.

19.08.2021

Regular Expressions

Bu konu bir blog yazısında anlatılacak kadar kısa bir konu değil; farkındayım. Ama konunun ana hatlarını yine de özetlemek istiyorum.

Bir metnin içinde (düzyazı, program, bir klasördeki dosya içerikleri, URL dizileri, dosys sistemi yolları vs) bir "dünya" var mı yok mu aramak istiyoruz. Örneğin bir klasördeki txt uzantılı dosyaların içinde. Bunu powershell ile yapmanın yolu

> Select-String -Pattern "dünya" -Path *.txt

Bu arama bize bazı sonuçlar döner. Ama diyelim ki dosyaların bazılarında "ü" yerine "u" kullanıldığını farkettik. Bu durumda "dunya" anahtar kelimesini de içerecek şekilde aramamızı değiştirelim. Ayrıca varsayılan parametre sıralaması ve alias kullanımıyla komutu biraz kısalatalım.

> sls "dünya|dunya" *.txt

"|" operatörü VEYA işlemi görür. Burada değişen 1 harf olduğu için bunu ü VEYA u şeklinde de yapabilirdik.

> sls "d[u|ü]nya" *.txt

Köşeli parantezler, bir karakter kümesi belirtmek için kullanılır. Örneğin sadece d,u,ü,n,y ve a'dan oluşan 5 veya 6 harfli kelimeleri bulmak istersek

> sls "[adnuüy]{5,6}" *.txt

yazabiliriz. Bu satırla sadece dünya ve dunya anahtar kelimelerini bulmakla kalmayacağız, ayrıca içinde herhangi bir sırada bu harflerin 5 veya 6'sı geçen başka kelimeleri de bulacağız. Ayrıca bunlar tam kelimeler de olmayacak, kelimenin herhangi bir bölümünde bu harflerin 5 veya 6'sının geçmesi yeterli olacak.

Bazı özel operatörleri listeleyelim:

?Önceki karakter 0 veya 1 kez geçecek
*Önceki karakter 0 veya daha fazla geçecek.
+Önceki karakter 1 veya daha fazla geçecek.
{n,}Önceki karakter n veya daha fazla geçecek.
{n,m}Önceki karakter en az n kere, en fazla m kere geçecek. Arasındaki sayılarda da olabilir.
. Yeni satır karakteri hariç her tekil karakteri bulur.
[a-z]Yalnızca "a" ve "z" arazındaki karakterleri bulur.
[^abc]a, b ve c olmayan her karakteri bulur.
^Satırın başını bulur.
$Satırın sonunu bulur.
( )Gruplandırma için. Parantezin içindeki ifade hatırlanır ve daha sonra \n veya $n gibi bir operatör ile kullanılabilir.
(?:)Aynen ( ) gibi gruplandırma için kullanılır, ama parantezin içindeki ifade hatırlanmaz
|veya operatörü
\wtüm harfleri bulur.
\Wharf olmayan karakterleri bulur.
\sBoşluk karakterlerini bulur.
\SBoşluk olmayan karakterleri bulur.
\dSayıları bulur.
\DSayı olmayanları bulur.
\AString'in başını bulur.
\ZString'in sonunu bulur. Bir yeni satır karakteri varsa ondan hemen öncesini bulur.
\zString'in sonunu bulur.Yeni satır karakterini de atlar.
\GEn son aramanın bulduğu noktanın bir sonrasını bulur.
\bKelime sınırlarını bulur.
\BKelime olmayan sınırları bulur\.

Bir string değişkenimiz olsun, aşağıdaki gibi

> $str1 = "Bugün günlerden Pazartesi"

Regular expression ifadelerimizin nasıl çalıştığını bu string üzerinde deneyerek görelim. Powershell'de -match  operatörü regular expression kullanır. Ama -like kullanmaz. Değiştirme operatörü -replace de regular expression kullanır. Değişkenin içinde "gün" geçiyor mu bakalım:

> $str1 -match "gun"

False

Sonuç altta "False" olarak verildi. "u" ve "ü" alternatifli olarak deneyelim:

> $str1 -match "g[u|ü]n"

True

Bu şekilde bir eşleşme bulundu. Pazartesi geçen kelimeleri Salı ile değiştirmek için

> $str1 -replace "Pazartesi","Salı"

Bugün günlerden Salı

Çok karşılaşılabilecek bir şey, ay\gün\yıl şeklinde yazılan tarihlerin gün.ay.yıl şeklinde çevrilmesi olabilir. Bunun için back reference denen gruplandırma operatörü olarak yukarıdaki tabloda listelediğim parantezleri kullanmalıyız. İşlem şu şekilde olacak, 2 haneli ay bilgisi bulunacak, 2 haneli gün bilgisi bulunacak, bunlar yer değiştirilecek ve ayraç olarak kullanılan "\" yerine "." konacak ve sonrasında gelen 4 haneli yıl bilgisi değiştirilmeyecek. Bunun için bulduğu gün, ay ve yıl verilerini hatırlaması gerekecek.

> $str1 = "bugün 11\20\1974"

> $str1 -replace '(\d{2})\\(\d{2})\\(\d{4})','$2.$1.$3'

bugün 20.11.1974

Burada çift tırnak yerine tek tırnak kullanmaya dikkat.

Çok sık yaşadığım bir konu, bir klasörde bir dosya arıyorum. Dosya adında geçen bir anahtar kelimeye göre aramak kolay. Ama 2 anahtar kelimem var ve hangisi önce gelecek, hangisi sonra gelecek, aralarında başka kelime olacak mı, bu ayrıntılar önemli değil. Sadece bu 2 anahtar kelimenin dosya adında geçmesini istiyorum. Bunun için yapılması gereken [3]:

> dir * | where {$_.Name -match "(?=.*format)(?=.*powershell)"}

Benzer şekilde bir klasördeki dosyaların içinde de geçmesini istediğim 2 anahtar kelime için arama yapabilirim:

> sls "(?=.*black)(?=.*star)" *-d.txt

---

[1] https://en.wikipedia.org/wiki/Regular_expression

[2] https://regexr.com/

[3] https://www.baeldung.com/string-contains-multiple-words

[4] https://www.regular-expressions.info/

[5] https://www3.ntu.edu.sg/home/ehchua/programming/howto/Regexe.html

[6] https://regex101.com/

[7] https://www.geeksforgeeks.org/write-regular-expressions/


16.08.2021

Powershell, diziler ve Add-Member

Şöyle bir hedefim var; Bir klasördeki dosyaları tablo olarak listelerken bir sütunda dosya sistemindeki sahip bilgisini de görmek istiyorum. Boş bir dizi oluşturayım.

> $dosyalar = @()

Sonra bu diziyi dosya bilgileri ile doldurayım.

> dir | % { $dosyalar += [PSCustomObject]@{

    Isim = $_.FullName

    Boyut = $_.Length

 }

Bu adımda $dosyalar dizisi şöyle olur:

Isim                          Boyut

-----                         -----

D:\Klasor\Dosya1.txt             22

D:\BaskaKlasor\Dosya2.doc      1366

Bu şekilde Isim ve Boyut sütunları olan bir dizi oluştu. Şimdi NTFS dosya sisteminde dosyayı oluşturan kullanıcı olan "sahip" (owner) bilgisini de eklemek istiyorum.

Oluşturma aşamasında da sahip bilgisini ekleyebilirdik, ama örnek olması açısından bu nesneye oluşturduktan sonra ekleyelim.

> Add-Member -InputObject $dosyalar -MemberType ScriptProperty -Name Sahip -Value {(Get-Acl $this.Isim).Owner}

Bu işlem sonunda şu şekilde bir tablomuz olur:

Isim                          Boyut    Sahip

-----                         -----    -----

D:\Klasor\Dosya1.txt             22    metin

D:\BaskaKlasor\Dosya2.doc      1366    arda

12.08.2021

Powershell ile metin dosyalarını incelemek

Grafik arayüzlü metin editörleri varken ne gerek var Powershell'e. Ama çok büyük metin dosyaları ile çalışırken bütün dosyayı açıp incelemek sorun olabilir. Çok büyük derken örneğin 250 GB. Bu kadar dosyayı açıp belleğe almak bile ciddi bir iş.

Onun yerine Get-Content ve Select-String gibi cmdlet'ler kullanılabilir mi?

Öncelikle alias'ları da kullanarak dosyanın başından 20 satırını bir inceleyelim.

> cat -TotalCount 20 .\network.log

Bir de sondan 20 satırı görelim

> cat -Tail 20 .\network.log

Buraya kadar gördüklerimizden dosyanın genel bütün satırlarının System.Net.Sockets ile başladığını gördük diyelim. Peki bununla başlamayanlar var mı? (bkz [1],[2])

> sls "^(?!System.Net.Sockets)" .\network.log

Ve diyelim ki dosyanın içinde bir IIS logu benzeri bir yapı bulduk. Virgülle ayrılmış değerler. İlk alan tarih, daha sonra saat, kaynak ve hedef IP adresleri, kaynak ve hedef portları gibi:

2021-08-10,09:38:22,192.168.7.3,8.8.8.8,1356,443

Bu satırlardan da sadece kaynak IP adresi ve kaynak hedef portu ile ilgileniyoruz. Bu alanları alıp ekrana basmak için kullanabileceğimiz ConvertFrom-String cmdlet'i var. -Delimiter parametresi ile verilen karakterlerle ayrılmış alanları ayrıştırıp P1'den P(N)'e kadar alan isimlerini otomatik yaratıp kullanımımıza sunuyor. Bizim örneğimizde kaynak IP ile hedef portu 4. ve 6. alanalar olduğu için bunları aşağıdaki gibi süzebiliriz:

> sls "^(?!System.Net.Sockets)" .\network.log | ConvertFrom-String | select P4,P6
 

P4        P6
-------   ---
8.8.8.8   443
1.1.1.1   443

gibi bir sonuç elde edilir.

 Dosyanın içinde 192.168 ile başlayan IP adresleri var mı diye bir bakalım:

> sls "192\.168\.\d{1,3}\.\d{1,3}" .\network.log

Ya da tarih (örneğin 2021-08-10 formatında) yazıyor mu hiç:

> sls "\d{4}-\d{2}-\d{2}" .\network.log

Belki de tarih formatımız 2021.08.10 veya 20210810 da olabilir:

> sls "\d{4}.?\d{2}.?\d{2}" .\network.log

Tüm bunları yaparken bütün dosyayı değil de ilk 1000 veya son 1000 satır üzerinden işlem yapmak da isteyebiliriz. Bunun için "|" operatörü ile cmdlet'leri bağlayabiliriz:

> cat -Totalcount 1000 .\network.log | sls "\d{4}.?\d{2}.?\d{2}"

---

[1] https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.1

[2] https://www.tutorialspoint.com/powershell/powershell_regex.htm