Regex Temelleri: grep ile Düzenli İfade Kullanımı

Sistem yöneticiliğinde günlük işlerin büyük bir kısmı metin içinde bir şeyler aramakla geçer. Log dosyalarında hata bulmak, konfigürasyon dosyalarında belirli parametreleri tespit etmek, kullanıcı listelerinde filtreleme yapmak… Bunların hepsinde grep kullanırsın. Ama grep‘i sadece düz kelime araması için kullanıyorsan, aracın gücünün belki yüzde onunu kullanıyorsun demektir. Regex, yani düzenli ifadeler, grep‘i gerçek anlamda güçlü bir araca dönüştüren şeydir. Bu yazıda regex temellerini grep bağlamında ele alacağız, gerçek dünya senaryolarıyla pekiştireceğiz.

Regex Nedir ve Neden Öğrenmeye Değer?

Regex, metin kalıplarını tanımlamak için kullanılan özel bir sözdizimi sistemidir. “Tam olarak bu kelimeyi bul” yerine “şu karakterlerle başlayan, şu uzunlukta olan ve şurada biten her şeyi bul” gibi ifadeler yazmanı sağlar. Bir kez öğrendiğinde grep, sed, awk, Python, JavaScript ve daha onlarca araçta kullanabilirsin. Yatırımın karşılığını çok hızlı alırsın.

grep ile üç farklı regex modu kullanabilirsin:

  • BRE (Basic Regular Expressions): Varsayılan mod, grep komutunun standart davranışı
  • ERE (Extended Regular Expressions): grep -E veya egrep ile kullanılır, daha fazla özellik sunar
  • PCRE (Perl Compatible Regular Expressions): grep -P ile kullanılır, en gelişmiş regex desteği

Günlük işlerde çoğunlukla ERE modunu tercih ederim çünkü daha temiz bir sözdizimi sunuyor. Ama temel öğrenme için BRE ile başlamak mantıklı.

Temel Regex Karakterleri

Nokta (.) – Herhangi Bir Karakter

Nokta karakteri, yeni satır dışında herhangi bir tek karakteri temsil eder.

# "log" ile başlayıp herhangi bir karakterle devam eden kalıpları bul
grep "log." /var/log/syslog

# 3 karakter uzunluğunda her kelimeyi bul (boşluklar arasında)
grep " ... " dosya.txt

Yıldız (*) – Sıfır veya Daha Fazla Tekrar

Yıldız, kendinden önceki karakterin sıfır veya daha fazla kez tekrar ettiğini belirtir.

# "error" veya "errorrr" gibi ifadeleri bul
grep "erro*r" /var/log/apache2/error.log

# "ab", "abb", "abbb" gibi kalıpları yakala
grep "ab*" access.log

Dikkat: * tek başına “herhangi bir şey” demez, önceki karakterin sıfır veya daha fazla tekrarı demektir. Bu, shell wildcard’larından farklıdır ve yeni başlayanların en çok takıldığı noktalardan biridir.

Şapka (^) ve Dolar ($) – Satır Başı ve Sonu

# Satır başında "ERROR" ile başlayan satırları bul
grep "^ERROR" /var/log/uygulama.log

# Satır sonu ".conf" ile biten satırları bul
grep ".conf$" dosya_listesi.txt

# Hem başlangıç hem bitiş - tam olarak "root" olan satırları bul
grep "^root$" /etc/passwd

Nokta karakterini literal olarak aramak için ters eğik çizgi ile kaçış yapman gerekir (.). Aksi halde regex motoru onu “herhangi bir karakter” olarak yorumlar.

Karakter Sınıfları – []

Köşeli parantezler içinde belirtilen karakterlerden herhangi biri olabilir anlamına gelir.

# Büyük veya küçük "e" ile başlayan "rror" içeren satırlar
grep "[Ee]rror" /var/log/syslog

# Rakam içeren satırları bul
grep "[0-9]" konfigürasyon.conf

# Rakam veya harf içeren satırlar
grep "[a-zA-Z0-9]" dosya.txt

# Başında büyük harf olan satırlar
grep "^[A-Z]" rapor.txt

Köşeli parantez içinde ^ kullanırsan anlam değişir ve “bunlar dışındaki karakterler” anlamına gelir:

# Rakam içermeyen satırları bul
grep "^[^0-9]*$" dosya.txt

grep Parametreleri

Regex örneklerine geçmeden önce, sık kullanılan grep parametrelerini bilmek gerekiyor:

  • -i: Büyük/küçük harf farkını gözetme
  • -v: Eşleşmeyen satırları göster (tersine çevir)
  • -r: Dizinleri özyinelemeli ara
  • -l: Sadece eşleşen dosyaların adlarını göster
  • -n: Satır numaralarını göster
  • -c: Eşleşen satır sayısını göster
  • -E: Genişletilmiş regex modunu kullan
  • -P: PCRE regex modunu kullan
  • -o: Sadece eşleşen kısmı göster, tüm satırı değil
  • -A n: Eşleşmeden sonraki n satırı da göster
  • -B n: Eşleşmeden önceki n satırı da göster
  • -w: Tam kelime eşleşmesi
  • –color: Eşleşen kısımları renklendir

Extended Regex ile Daha Güçlü Kalıplar

grep -E kullanarak çok daha esnek ifadeler yazabilirsin.

Artı (+) ve Soru İşareti (?)

# En az bir rakam içeren satırlar (+ işareti: bir veya daha fazla)
grep -E "[0-9]+" /var/log/auth.log

# "colour" veya "color" - u harfi isteğe bağlı (? işareti: sıfır veya bir)
grep -E "colou?r" kelimeler.txt

# HTTP durum kodlarını bul (3 haneli rakam)
grep -E "[0-9]{3}" /var/log/apache2/access.log

Süslü Parantezler {} – Belirli Tekrar Sayısı

# Tam olarak 3 haneli sayılar
grep -E "[0-9]{3}" dosya.txt

# 2 ile 4 arasında tekrar eden 'a' harfi
grep -E "a{2,4}" dosya.txt

# En az 5 karakter uzunluğunda kelimeler
grep -E "[a-z]{5,}" dosya.txt

Pipe (|) – Ya Bu Ya O

# "error" veya "warning" içeren satırlar
grep -E "error|warning|critical" /var/log/syslog

# TCP veya UDP içeren satırlar
grep -E "TCP|UDP" /var/log/firewall.log

Parantezler – Gruplama

# "restart" veya "reboot" içeren satırlar
grep -E "re(start|boot)" /var/log/syslog

# IP adresi kalıbı (basit versiyon)
grep -E "([0-9]{1,3}.){3}[0-9]{1,3}" access.log

Gerçek Dünya Senaryoları

Senaryo 1: Apache/Nginx Log Analizi

Prodüksiyon sunucusunda yoğun trafik var ve hangi IP adreslerinin 404 hatası aldığını bulmak istiyorsun.

# 404 hatası veren tüm satırları bul ve IP adreslerini çıkar
grep -E " 404 " /var/log/apache2/access.log | grep -oE "^[0-9.]+"

# Son 1 saatteki 5xx hatalarını bul
grep -E " 5[0-9]{2} " /var/log/apache2/access.log | tail -100

# Belirli bir IP'nin tüm isteklerini bul
grep -E "^192.168.1.[0-9]+" /var/log/nginx/access.log

# POST isteklerini bul ve kaç tane olduğunu say
grep -c '"POST' /var/log/nginx/access.log

Senaryo 2: SSH Brute Force Tespiti

Sunucuna SSH ile kaba kuvvet saldırısı olup olmadığını kontrol etmek istiyorsun.

# Başarısız SSH giriş denemelerini bul
grep -E "Failed password|Invalid user" /var/log/auth.log

# Hangi kullanıcı adlarıyla deneme yapılmış
grep -oE "invalid user [a-zA-Z0-9_]+" /var/log/auth.log | sort | uniq -c | sort -rn

# Hangi IP'lerden saldırı geliyor
grep "Failed password" /var/log/auth.log | grep -oE "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" | sort | uniq -c | sort -rn | head -20

# Belirli bir tarih aralığındaki başarısız girişler
grep -E "^Jan (1[5-9]|2[0-9])" /var/log/auth.log | grep "Failed password"

Senaryo 3: Konfigürasyon Dosyası Yönetimi

Onlarca sunucuda aynı konfigürasyon dosyasını kontrol etmek gerekiyor.

# /etc altındaki tüm .conf dosyalarında "deprecated" ifadesini bul
grep -r "deprecated" /etc/*.conf

# Yorum satırı olmayan aktif konfigürasyonları göster
grep -vE "^#|^$" /etc/nginx/nginx.conf

# Port numarası içeren satırları bul
grep -E "ports+[0-9]+" /etc/ssh/sshd_config

# Belirli bir IP bloğunun izin verildiği yerleri bul
grep -rE "allows+192.168." /etc/nginx/

# Boş olmayan ve yorum olmayan satır sayısını bul
grep -cE "^[^#]" /etc/apache2/apache2.conf

Senaryo 4: Sistem Log Analizi

Bir serviste sorun var ve log dosyasında ne zaman başladığını bulmak istiyorsun.

# Belirli bir zaman aralığındaki hataları bul
grep -E "^2024-01-15 (1[4-8]):" /var/log/uygulama.log | grep -i "error"

# Hata mesajından önceki ve sonraki 5 satırı göster (bağlam için)
grep -A 5 -B 5 "OutOfMemoryError" /var/log/uygulama.log

# Birden fazla servise ait log satırlarını filtrele
grep -E "(nginx|mysql|php-fpm)" /var/log/syslog | grep -i "error"

# Sadece timestamp ve hata mesajını çıkar
grep -oE "^[0-9-]+ [0-9:]+ .*(ERROR|WARN).*" /var/log/uygulama.log

Email ve IP Doğrulama Kalıpları

Sysadmin olarak kullanıcı girdilerini veya log dosyalarını doğrularken bu kalıpları sıkça kullanırsın.

# Basit email adresi kalıbı
grep -E "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}" kullanici_listesi.txt

# IPv4 adresi - daha katı versiyon
grep -P "b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b" dosya.txt

# MAC adresi bul
grep -E "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}" network.log

# URL kalıbı
grep -E "https?://[a-zA-Z0-9./%-]+" access.log

POSIX Karakter Sınıfları

Daha okunabilir kalıplar için POSIX karakter sınıflarını kullanabilirsin:

  • [:alpha:]: Harf karakterleri (a-z, A-Z)
  • [:digit:]: Rakamlar (0-9)
  • [:alnum:]: Harf ve rakamlar
  • [:space:]: Boşluk karakterleri
  • [:upper:]: Büyük harfler
  • [:lower:]: Küçük harfler
  • [:punct:]: Noktalama işaretleri
# Sadece rakam içeren satırlar
grep "^[[:digit:]]*$" dosya.txt

# Büyük harfle başlayan satırlar
grep "^[[:upper:]]" rapor.txt

# Boşluk içeren satırları bul
grep "[[:space:]]" konfigürasyon.txt

# Alfanümerik olmayan karakterleri içeren satırlar
grep "[^[:alnum:][:space:]]" dosya.txt

Performans İpuçları

Büyük log dosyalarında regex araması yaparken performans önemli hale gelir.

# Önce basit string araması yap, sonra regex ile filtrele (daha hızlı)
grep "ERROR" /var/log/büyük_dosya.log | grep -E "^2024-01-15"

# fgrep (sabit string arama) regex gerektirmeyen durumlarda çok daha hızlı
fgrep "exact string" büyük_dosya.log

# Birden fazla pattern yerine tek bir -E kullan
grep -E "error|warning|critical" dosya.log
# Bu, üç ayrı grep pipe'ından çok daha verimlidir

# Büyük dosyalarda --mmap bazen daha hızlı olabilir
grep --mmap -E "kalıp" çok_büyük_dosya.log

Sık Yapılan Hatalar ve Çözümleri

Hata 1: Nokta karakterini kaçırmak

# Yanlış - 192.168.1.1 yerine 192X168Y1Z1 gibi şeyler de eşleşir
grep "192.168.1.1" dosya.txt

# Doğru - noktalı literal arama
grep "192.168.1.1" dosya.txt

Hata 2: Greedy matching

# HTML taglerini bulmak istiyorsun ama çok fazla eşleşiyor
grep -oE "<.*>" sayfa.html  # <b>kalın</b> yerine tüm satırı alabilir

# Daha spesifik kalıp kullan
grep -oE "<[^>]+>" sayfa.html

Hata 3: BRE ve ERE farkını unutmak

# BRE'de + ve ? literal karakter, ERE'de özel anlam taşır
grep "a+" dosya.txt    # literal "a+" arar
grep -E "a+" dosya.txt  # bir veya daha fazla "a" arar

# BRE'de özel karakterleri kaçış ile kullanmak gerekir
grep "a+" dosya.txt    # BRE'de bir veya daha fazla "a"

Pratik Tek Satırlık Komutlar

Günlük işlerde zaman kazandıran bazı hazır kalıplar:

# Sistemdeki tüm cron job'larını listele
grep -rE "^s*[^#]" /etc/cron* /var/spool/cron* 2>/dev/null

# Bir dizindeki tüm PHP dosyalarında SQL injection açığı işareti ara
grep -rE "\$_(GET|POST|REQUEST)[" /var/www/html/ --include="*.php"

# Sudoers dosyasında belirli kullanıcıları bul
grep -E "^%?(sudo|wheel|admin)" /etc/sudoers

# Sistemde SUID bit'li dosyaları listele (ls çıktısında)
ls -la /usr/bin/ | grep -E "^...s"

# Network konfigürasyonunda gateway bul
grep -E "GATEWAY|gateway" /etc/network/interfaces /etc/sysconfig/network* 2>/dev/null

# Aktif dinlenen portları bul
ss -tlnp | grep -E ":[0-9]+" | grep -oE ":[0-9]+" | sort -u

Regex’i Öğrenmek için Pratik Yaklaşım

Regex öğrenmek biraz zaman alır ama sistematik yaklaşırsan hızlanırsın. İlk önce temel meta karakterleri ezberle: ., *, ^, $, []. Sonra ERE’ye geç ve +, ?, {}, |, () ekle. Her yeni kavramı gerçek bir log dosyası üzerinde dene.

grep --color=always kullanmak başlangıçta çok yardımcı olur. Regex’in neyi yakaladığını görsel olarak görmek, kalıpları anlamayı kolaylaştırır. Ayrıca [regex101.com](https://regex101.com) gibi siteler online test etmek için kullanışlıdır, ama son sözü her zaman terminalde çalıştırarak ver.

Kendi “regex kütüphaneni” bir dosyada tutmaya başla. Çalışan bir IP adresi kalıbı buldun mu, bir email regex’i yazdın mı? Bunları not al. Zamanla kendi araç kutunu oluşturursun ve aynı problemi tekrar tekrar çözmek zorunda kalmazsın.

Sonuç

grep ve regex, sysadmin araç kutusunun çekirdeğindedir. Log analizinden güvenlik denetimlerine, konfigürasyon yönetiminden veri çıkarmaya kadar her yerde karşına çıkar. Bu yazıda temel meta karakterlerden başlayıp gerçek dünya senaryolarına kadar geniş bir yelpazede anlattım. Tüm bunları bir seferde ezberlemek zorunda değilsin. Önemli olan, bir sorunla karşılaştığında “bunu regex ile çözebilirim” diye düşünmeye başlamak ve denemeye devam etmektir.

Bir sonraki yazıda sed ile regex kullanımına bakacağız. grep‘in bulduğunu sed ile değiştirip, dönüştürüp, silebileceğini göreceğiz. O birleşim gerçekten güçlü.

Yorum yapın