PowerShell - Dosyadaki Dizeyi Bul [4 Yol]
1. Genel Bakış
Metin dosyalarındaki dizeleri aramak, PowerShell'de günlük dosyası analizi ve yapılandırma dosyası aramaları gibi senaryolarda kullanılan yaygın bir görevdir. Bu makalede, hem büyük/küçük harfe duyarlı hem de büyük/küçük harfe duyarlı olmayan yaklaşımlar dahil, dosyalarda dize bulmaya yönelik çeşitli yöntemler araştırılmaktadır.
2. Problem İfadesine Giriş
server.log adında bir günlük dosyası düşünelim:
Server.log'un içeriği:
2023-11-24 10:00:00 INFO Starting server process
2023-11-24 10:00:05 ERROR Failed to bind to port 8080
2023-11-24 10:00:10 INFO Server listening on port 9090
2023-11-24 10:01:00 ERROR Database connection timeoutAmacımız bu dosyada Error dizisinin oluşumlarını bulmaktır.
Beklenen çıktı "Hata" içeren satırlardır.
Beklenen Çıktı:
2023-11-24 10:00:05 ERROR Failed to bind to port 8080
2023-11-24 10:01:00 ERROR Database connection timeoutEk olarak, hem büyük/küçük harfe duyarlı hem de büyük/küçük harfe duyarlı olmayan arama yöntemlerini inceleyeceğiz.
3. Get-Content ve Select-String Cmdlet'lerini Kullanma
Bu yöntem, Get-Content cmdlet'ini kullanarak dosya içeriğinin okunmasını ve dosyada gerekli dizenin aranması için çıktısının Select-Stirng cmdlet'ine aktarılmasını içerir.
Get-Content ve Select-String Cmdlet'lerini kullanma:
Get-Content server.log | Select-String _Pattern "Error"Açıklama:
Get-Content server.log: Server.log içeriğini okur.
|: Verileri yönlendirir Get-Content komutunun Select-String'e çıktısı.
Select-String -Pattern "Error": Şunu arar: Kanaldan alınan girişte "Hata" dizisi.
Bu komut, server.log dosyasındaki Error kalıbını arar ve Get-Content dosyanın tamamını belleğe okuduğu için büyük dosyalarda daha yavaş olabilir. Varsayılan olarak büyük/küçük harfe duyarlı değildir. Büyük/küçük harfe duyarlı hale getirmek için -CaseSensitive flagını kullanabiliriz.
Get-Content ve Select-String Cmdlet'lerini kullanma:
Get-Content server.log | Select-String _Pattern "Error" -CaseSensitive4. Select-String Cmdlet'ini Doğrudan Kullanma
Diğer bir yöntem ise Select-String Cmdlet'ini Doğrudan kullanmaktır.
Select-String Cmdlet'ini Kullanma:
Select-String -Path server.log -Pattern "Error"Açıklama:
Select-String: Dize araması için kullanılan cmdlet.
-Path sunucusu.log: dosya yolu.
-Desen "Hata": Aranacak dize modelini tanımlar.
Bu komutun çıktısı şöyle olacaktır:
Çıkış:
server.log.txt:2:2023-11-24 10:00:05 ERROR Failed to bind to port 8080
server.log.txt:4:2023-11-24 10:01:00 ERROR Database connection timeoutDosya adını ve satır numarasını çıktının dışında bırakmak için aşağıdaki komutu kullanabiliriz:
Select-String Cmdlet'ini Kullanma:
Select-String -Path server.log -Pattern "Error" -SimpleMatch | ForEach-Object { $_.Line }Yukarıdaki komutu daha ayrıntılı olarak anlayalım:
$_ olarak temsil edilen Select-String tarafından oluşturulan her eşleşme nesnesini alır ve yalnızca <'yi çıkarır..Line özelliği, satırın gerçek metnini içerir.
Şimdi beklenen çıktı aşağıdaki gibi olacaktır:
Beklenen Çıktı:
2023-11-24 10:00:05 ERROR Failed to bind to port 8080
2023-11-24 10:01:00 ERROR Database connection timeoutBu yaklaşım, sonuçların dosya adını ve satır numarasını çıkararak çıktının yalnızca arama dizesini içeren satırların metnini içermesini sağlar.
String içerisinde desen ararken normal ifade ile Select-String komutunu da kullanabiliriz.
Diyelim ki Error dizesinin ardından sayının gelmesi gereken desen aramak istediğimizi varsayalım.
Select-String cmdlet'ini kullanma:
Select-String -Path server.log -Pattern 'Error\d+' -AllMatchesBu komut, Error ve ardından sayılar içeren satırları görüntüler. -AllMatches bayrağı dışında yukarıdaki komuta benzer. AllMatches belirli bir düzenin tüm eşleşmelerini döndürür.
Bu yöntem ayrıca varsayılan olarak büyük/küçük harfe duyarlı değildir. Büyük/küçük harfe duyarlı hale getirmek için -CaseSensitive flagını kullanabiliriz.
Get-Content ve Select-String Cmdlet'lerini kullanma:
Select-String -Path server.log -Pattern "Error" -CaseSensitive -SimpleMatch | ForEach-Object { $_.Line }5. Get-Content'in -ReadCount Parametresi ve -Match Operatörü ile Kullanımı
Bu yaklaşım büyük dosyalarla uğraşırken kullanılabilir. Büyük dosyaları parçalar halinde işleyerek okumayı optimize eder.
Örnek yardımıyla görelim:
GetContent'i -Match operatörüyle kullanma:
(Get-Content server.log -ReadCount 1000) -match "Error"(Get-Content server.log -ReadCount 1000): Belleği parçalar halinde, tek seferde 1000 satır okur.
-eşleşme "Hata": Dosya parçalarında "Hata" kalıbı.
Basit bir ifadeyle, Get-Content dosyanın parçalarını okuduktan sonra -match "Error" operatörü uygulanır. Bu operatör her bir öbeği filtreler ve yalnızca "Hata" dizesini içeren satırları döndürür. Eşleşme varsayılan olarak büyük/küçük harfe duyarlı değildir.
Bu yöntem büyük dosyalar için daha hızlı ve hafıza açısından verimli olabilir.
-match varsayılan olarak büyük/küçük harfe duyarlı olmadığından -cmatch operatörünü büyük/küçük harfe duyarlı arama için kullanabiliriz.
6. foreach Döngüsünü if Block ile Kullanmak
Diğer bir yöntem ise if bloğu ile foreach döngüsünü kullanmaktır. Bu yaklaşım yavaştır ancak her satırı ayrı ayrı işlerken kullanışlıdır.
Örnek yardımıyla görelim:
Foreach döngüsünü kullanma:
foreach ($line in Get-Content server.log) { if ($line -match "Error") { $line } }Açıklama:
foreach (Get-Content sunucusu.log'daki $satır): Dosyanın her satırında yinelenir.
if ($line -match "Error") { $line >: Satırın "Error içerip içermediğini kontrol eder ve doğruysa çıktısını verir.
Yani her satırı yinelerken, eğer satırda Kalıp Hatası bulunuyorsa, onu yazdıracaktır.
Yine burada da büyük/küçük harfe duyarlı arama için -cmatch operatörünü kullanabiliriz.
7. Dosyada Birden Fazla Desen Arama
Senaryo üzerinde çalışırken çoğu zaman tek bir kalıp yerine çoklu kalıplara göre arama yapmamız gereken durumlar vardır.
Bunu yapmanın birden fazla yolu var. Örnekler yardımıyla görelim:
Select-String çoklu desenleri:
Select-String -Path server.log -Pattern "Error", "Warning", "Failed"Bu komut, server.log'da listelenen kalıplardan herhangi birini ("Hata", "Uyarı", "Başarısız") arar.
Bunu normal ifadeler kullanarak birleştirmek.
Select-String çoklu desenleri:
Select-String -Path server.log -Pattern "Error|Warning|Failed-ReadCount ile İçerik Alın:
(Get-Content server.log -ReadCount 1000) -match "Error|Warning|Failed"Select-String'i bir dizi desenle kullanma
Select-String çoklu desenleri:
$patterns = "Error", "Warning"; Select-String -Path server.log -Pattern $patternsGelişmiş kalıp eşleştirme için komut dosyası bloklarını kullanma
Komut dosyası bloklarını kullanma:
Get-Content server.log | Where-Object { $_ -match "Error" -or $_ -match "Warning" 8. Dizin ve Alt Dizinlerdeki Dizeleri Arama
İstenilen metin için birden fazla dosyanın kapsamlı bir şekilde taranmasını sağlayarak yalnızca tek bir dosyada değil, tüm bir dizinde ve alt dizinlerinde belirli dizeleri nasıl arayacağınızı keşfedelim.
Bu, Get-ChildItem ve Select-String kombinasyonunu kullanıyor olabilir.
Dizin ve Alt Dizinlerdeki Dizeleri Arama:
Get-ChildItem -Path C:\Logs -Recurse | Select-String -Pattern "Error"Get-ChildItem -Path C:\Logs -Recurse: C:\Logs ve alt dizinlerindeki tüm dosyaları alır. Select-String'e aktarıldığında, her dosyada belirtilen modeli arar.
Şimdi sadece .log uzantılı dosyalarda desen aramak istersek ne olur? Bu, -Include bayrağı kullanılarak gerçekleştirilebilir.
Dizin ve Alt Dizinlerdeki Dizeleri Arama:
Get-ChildItem -Path C:\Logs -Recurse -Include *.log | Select-String -Pattern "Error"Bu komut öncekine benzer ancak aramayı belirli bir uzantıya sahip dosyalarla (ör. .log) sınırlandırır. Karışık dosya türlerine sahip dizinler arasında arama yaparken etkilidir.
9. Performans Karşılaştırması
En iyisini seçebilmemiz için her yöntemin ne kadar hızlı çalıştığını test etmek önemlidir.
1 milyon satırlık büyük bir server.log girdisi oluşturacağız ve bunun üzerindeki her çözümü, dosyadaki "Hata" kalıbını arayacak şekilde test edeceğiz.
Performanslarını karşılaştırın, Measure-Command cmdlet'ini kullanacağız. Her yöntemin performansını ölçen komut dosyası:
Performans ölçüsü:
# Define the file and search pattern
$filePath = "server.log"
$searchPattern = "Error"
# Method 1: Using Get-Content and Select-String
$method1 = {
Get-Content $filePath | Select-String $searchPattern
}
# Method 2: Using Select-String Directly
$method2 = {
Select-String -Path $filePath -Pattern $searchPattern -SimpleMatch | ForEach-Object { $_.Line }
}
# Method 3: Get-Content with -ReadCount and -Match
$method3 = {
(Get-Content $filePath -ReadCount 1000) -match $searchPattern
}
# Method 4: Using foreach Loop
$method4 = {
foreach ($line in Get-Content $filePath) { if ($line -match $searchPattern) { $line } }
}
# Measure and output the time for each method
"Method 1 Time: $(Measure-Command $method1).TotalMilliseconds ms"
"Method 2 Time: $(Measure-Command $method2).TotalMilliseconds ms"
"Method 3 Time: $(Measure-Command $method3).TotalMilliseconds ms"
"Method 4 Time: $(Measure-Command $method4).TotalMilliseconds ms"Şimdi test sonuçlarına bakalım:
test sonuçları:
Method 1 Time: 00:00:20.2374519.TotalMilliseconds ms
Method 2 Time: 00:00:05.2277779.TotalMilliseconds ms
Method 3 Time: 00:00:03.6214583.TotalMilliseconds ms
Method 4 Time: 00:01:10.4835464.TotalMilliseconds msHer yöntemin çıktı sürelerine göre:
Yöntem 1 (Get-Content ve Select-String Kullanımı): Yaklaşık 20,24 saniye sürdü.
Yöntem 2 (Doğrudan Select-String Kullanımı): Yaklaşık 5,23 saniye sürdü .
Yöntem 3 (Get-Content'i -ReadCount ve -Match ile kullanmak): Yalnızca 3,62 saniye sürerek en hızlısıydı.
Yöntem 4 (foreach kullanmak) Döngü): Yaklaşık 70,48 saniye sürerek en yavaş olanıydı.
10. Sonuç
Özetle, farklı PowerShell dize arama yöntemlerinin performansı büyük ölçüde farklılık gösterir. Dosyaları parçalar halinde okuyan en hızlı yöntem, hızı ve verimliliği nedeniyle büyük dosyalar için idealdir. Doğrudan desen eşleştirme yöntemleri, basit aramalar için basitlik ve hız arasında iyi bir denge sunar. Bununla birlikte, her satırı ayrı ayrı işleyen en yavaş yaklaşım, ayrıntılı analiz için veya aramanın kapsamlılığının hız ihtiyacından daha ağır bastığı daha küçük dosyalarla çalışırken en iyisidir. Yöntem seçimi, dosya boyutu ve arama karmaşıklığı dikkate alınarak görevin özel ihtiyaçlarına göre yapılmalıdır.
