pcregrep ile Perl Uyumlu Regex: Çok Satırlı Desen Eşleştirme ve Gelişmiş Arama Teknikleri

Yıllarca grep ile idare ettim, itiraf edeyim. Standart regex yeterliydi çoğu zaman, kimse de şikayet etmiyordu. Ta ki bir gün production log dosyalarında çok satırlı hata bloklarını ayıklamam gerekene kadar. O gün pcregrep ile tanıştım ve hayatım bir daha eskisi gibi olmadı. Biraz dramatik kulağa geliyor, biliyorum, ama metin işleme dünyasında Perl uyumlu regex’in ne anlama geldiğini bir kez yaşayınca anlıyorsunuz.

pcregrep Nedir ve Neden Önemsememiz Gerekir

pcregrep, PCRE (Perl Compatible Regular Expressions) kütüphanesini kullanan, grepin daha güçlü bir alternatifidir. Standart grep POSIX regex kullanır, GNU grep ise -P flag’i ile sınırlı düzeyde PCRE desteği sunar. Ama pcregrep baştan aşağı PCRE için tasarlanmıştır ve özellikle çok satırlı eşleştirme konusunda rakipsizdir.

Temel fark şurada: standart grep satır bazlı çalışır. Her satırı bağımsız bir birim olarak değerlendirir. pcregrep ise -M flag’i ile birden fazla satırı tek bir blok olarak ele alabilir. Bu, özellikle stack trace’ler, XML/JSON blokları ve çok satırlı log girişleri için çığır açan bir özelliktir.

Kurulum oldukça basit:

# Debian/Ubuntu
sudo apt-get install pcregrep

# RHEL/CentOS/Rocky Linux
sudo yum install pcre-tools
# veya
sudo dnf install pcre-tools

# macOS (Homebrew)
brew install pcre

Kurulumu doğrulamak için:

pcregrep --version
# pcregrep 8.45 2021-06-15

Temel Kullanım ve Parametre Rehberi

Önce temel parametreleri tanıyalım, sonra gerçek senaryolara geçeceğiz.

-M veya –multiline: Çok satırlı mod, . karakterinin newline’ı da eşleştirmesini sağlar -i: Büyük/küçük harf duyarsız arama -n: Satır numaralarını göster -l: Sadece eşleşen dosya adlarını listele -L: Eşleşme olmayan dosyaları listele -r: Dizinleri özyinelemeli tara -v: Eşleşmeyen satırları göster (invert match) -c: Eşleşme sayısını göster -o: Sadece eşleşen kısmı göster -A n: Eşleşmeden sonra n satır göster -B n: Eşleşmeden önce n satır göster -C n: Eşleşmenin hem öncesinde hem sonrasında n satır göster –color: Eşleşmeleri renkli göster -e pattern: Birden fazla desen belirlemek için kullanılır -f dosya: Desenleri dosyadan oku –om-separator: -o ile birden fazla eşleşme arasına ayraç koy

Basit bir örnekle başlayalım:

# Standart grep ile aynı temel kullanım
pcregrep "ERROR" /var/log/syslog

# Büyük/küçük harf duyarsız, satır numaralı
pcregrep -in "error|warning" /var/log/application.log

# Birden fazla desen
pcregrep -e "OutOfMemory" -e "StackOverflow" /var/log/app.log

Çok Satırlı Eşleştirme: Asıl Güç Burada

pcregrepin standart araçlardan ayrıldığı en kritik nokta burası. -M flag’i ile satır sınırlarını aşan desenleri yakalayabilirsiniz.

Diyelim ki şöyle bir Java stack trace’i var:

2024-01-15 14:23:11 ERROR Application crashed
java.lang.NullPointerException: Cannot invoke method
    at com.example.UserService.getUser(UserService.java:45)
    at com.example.Controller.handle(Controller.java:78)
2024-01-15 14:23:12 INFO Server still running

Bu bloğu bir bütün olarak yakalamak için:

# -M ile çok satırlı mod
pcregrep -M "ERROR.*njava.lang." /var/log/app.log

# Daha geniş bir blok yakalamak için
pcregrep -M "ERROR.*n(.*n){1,10}.*at com.example." /var/log/app.log

Gerçek hayattan bir senaryo: Nginx access log’larında belirli bir IP’nin art arda 5xx hatası aldığı blokları tespit etmeniz gerekiyor. Bu durumda çok satırlı eşleştirme ile kombinasyon yapabilirsiniz.

# Belirli bir IP'den gelen 5xx hatalarını çok satırlı bloklar halinde yakala
pcregrep -M "192.168.1.100.*" 5[0-9]{2}" /var/log/nginx/access.log

PCRE’nin Özel Gücü: Lookahead ve Lookbehind

Standart grepte olmayan ama pcregrepte kullanabileceğiniz en değerli özelliklerden biri lookahead (ileri bakış) ve lookbehind (geri bakış) assertions’larıdır. Eşleşmenin kendisini değil, etrafındaki bağlamı kontrol ederler.

Lookahead örnekleri:

# "password" kelimesinden sonra ":" gelenleri bul (password: kısmını yakala ama ":" gösterme)
pcregrep -o "password(?=:)" config.txt

# "ERROR" ile başlayan ama "timeout" içermeyen satırları bul
pcregrep "ERROR(?!.*timeout)" /var/log/app.log

# Sayıdan önce "port" kelimesi gelenler
pcregrep -o "(?<=port )d+" nginx.conf

Lookbehind örnekleri:

# "user=" den sonra gelen kullanıcı adını çıkar
pcregrep -o "(?<=user=)[a-zA-Z0-9_]+" auth.log

# Fiyat işaretinden sonra gelen rakamları bul
pcregrep -o "(?<=$)d+.d{2}" invoices.txt

Gerçek dünya senaryosu: Apache log’larından sadece authenticated kullanıcıların yaptığı 404 isteklerini çıkarmak istiyorsunuz.

# Auth başarılı olmuş (200 auth response geçmiş) ama 404 alan istekler
pcregrep "(?<=" )404(?= )" /var/log/apache2/access.log | 
    pcregrep -v "(?<=" 401 )"

Named Capture Groups ile Yapılandırılmış Veri Çıkarma

PCRE’nin bir diğer süper özelliği named capture groups. Log’lardan yapılandırılmış veri çıkarırken bu özellik son derece işe yarar.

# IP adresi ve HTTP status kodunu named group ile yakala
pcregrep -o "(?P<ip>d{1,3}.d{1,3}.d{1,3}.d{1,3}).*(?P<status>[45]d{2})" 
    /var/log/nginx/access.log

Bir script içinde kullanımı daha da anlamlı hale gelir. Örneğin bir monitoring scripti yazıyorsunuz:

#!/bin/bash
# Son 1 saatin kritik hatalarını çıkar ve raporla

LOG_FILE="/var/log/application.log"
REPORT_FILE="/tmp/error_report_$(date +%Y%m%d_%H).txt"

echo "=== Hata Raporu ===" > "$REPORT_FILE"
echo "Tarih: $(date)" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

# PCRE ile karmaşık desenleri yakala
pcregrep -n 
    "(?i)(critical|fatal|error).*(?:exception|failure|crash)" 
    "$LOG_FILE" >> "$REPORT_FILE"

# Eşleşme sayısını da raporla
ERROR_COUNT=$(pcregrep -c 
    "(?i)(critical|fatal|error).*(?:exception|failure|crash)" 
    "$LOG_FILE")

echo "" >> "$REPORT_FILE"
echo "Toplam kritik hata sayısı: $ERROR_COUNT" >> "$REPORT_FILE"

# Eğer 10'dan fazla hata varsa uyarı gönder
if [ "$ERROR_COUNT" -gt 10 ]; then
    echo "KRİTİK: Son 1 saatte $ERROR_COUNT hata tespit edildi!" | 
        mail -s "Alarm: Yüksek Hata Oranı" [email protected]
fi

echo "Rapor oluşturuldu: $REPORT_FILE"

Özyinelemeli Arama ve Dosya Filtreleme

Büyük kod tabanlarında veya log dizinlerinde çalışırken özyinelemeli arama vazgeçilmez olur.

# Tüm Python dosyalarında güvensiz fonksiyon kullanımını tara
pcregrep -r --include="*.py" 
    "(?i)(eval|exec|pickle.loads|subprocess.call.*shell=True)" 
    /opt/myapp/

# Config dosyalarında şifrelenmemiş credential'ları bul
pcregrep -r --include="*.conf" --include="*.yaml" --include="*.yml" 
    "(?i)(password|passwd|secret|api_key)s*[:=]s*['"]?[^'"s]{8,}" 
    /etc/ 2>/dev/null

# Belirli dosyaları hariç tutarak arama
pcregrep -r --exclude="*.log.gz" --exclude="*.bak" 
    "TODO|FIXME|HACK" 
    /var/www/html/

Log rotasyon yapıldıktan sonra bile eski dosyalarda arama yapmak gerekebilir:

# Sıkıştırılmış log'ları da dahil ederek ara
# (zgrep ile birlikte kullanım)
for logfile in /var/log/nginx/access.log*; do
    if [[ "$logfile" == *.gz ]]; then
        zcat "$logfile" | pcregrep "(?i)sql.*injection|union.*select"
    else
        pcregrep "(?i)sql.*injection|union.*select" "$logfile"
    fi
done

Gerçek Dünya Senaryosu: Güvenlik Denetimi

Bir güvenlik denetimi senaryosu yaşadım geçen yıl. Web uygulama log’larında SQL injection girişimlerini tespit etmem gerekiyordu. Standart grep desenleri çok fazla false positive üretiyordu. pcregrep ile yazdığım desen hem daha hassas hem daha kapsamlıydı:

# SQL Injection pattern - gelişmiş PCRE deseni
pcregrep -i 
    "(?:unions+(?:alls+)?select|selects+.*s+from|inserts+into|drops+table|exec(?:ute)?s*(|xp_cmdshell)" 
    /var/log/apache2/access.log | 
    pcregrep -v "(?:googlebot|bingbot|health.?check)" | 
    awk '{print $1}' | sort | uniq -c | sort -rn | head -20

Bununla da kalmayıp, şüpheli IP’lerin davranış örüntüsünü çok satırlı analizle inceledim:

#!/bin/bash
# Şüpheli IP davranış analizi

SUSPICIOUS_IP="$1"
LOG_FILE="/var/log/apache2/access.log"

echo "IP: $SUSPICIOUS_IP için davranış analizi"
echo "============================================"

echo -e "n[1] Toplam istek sayısı:"
pcregrep "^$SUSPICIOUS_IP " "$LOG_FILE" | wc -l

echo -e "n[2] HTTP metod dağılımı:"
pcregrep -o ""(?:GET|POST|PUT|DELETE|OPTIONS|PATCH)[^"]*"" 
    <(pcregrep "^$SUSPICIOUS_IP " "$LOG_FILE") | 
    grep -oP "^"[A-Z]+" | sort | uniq -c | sort -rn

echo -e "n[3] 4xx ve 5xx hatalar:"
pcregrep "^$SUSPICIOUS_IP .*" [45][0-9]{2} " "$LOG_FILE" | wc -l

echo -e "n[4] Şüpheli payload'lar:"
pcregrep -i "^$SUSPICIOUS_IP .*(?:etc/passwd|/proc/self|../|<script|javascript:)" 
    "$LOG_FILE"

Desenlerinizi Dosyadan Okumak

Büyük bir desen koleksiyonunuz varsa, bunları doğrudan komut satırına yazmak hem pratik değil hem de hata oranını artırır. -f parametresi ile desenleri dosyadan okuyabilirsiniz:

# patterns.txt dosyası oluştur
cat > /etc/pcregrep-patterns/security.txt << 'EOF'
(?i)(?:select|insert|update|delete|drop|union)s+
(?i)(?:script|javascript|vbscript|onload|onerror)s*=
(?i)(?:../){2,}
(?i)(?:cmd.exe|/bin/sh|/bin/bash)s*
(?i)(?:wget|curl)s+http
EOF

# Bu desenleri kullanarak tarama yap
pcregrep -f /etc/pcregrep-patterns/security.txt 
    /var/log/nginx/access.log

Performans İpuçları

Production ortamında büyük log dosyalarıyla çalışırken performans kritik olabilir.

# Büyük dosyalarda grep ile ön filtreleme yapıp pcregrep'e aktar
# (basit desen için grep daha hızlı çalışır)
grep "ERROR" /var/log/huge-app.log | 
    pcregrep "(?:NullPointer|OutOfMemory|StackOverflow)Exception.*batb"

# Paralel işlem için GNU parallel ile kullan
ls /var/log/nginx/access.log.* | 
    parallel "pcregrep -c 'pattern' {} | awk -v f={} '{print f": "$1}'"

# Sadece gerekli alanları çıkar, tüm satırı taşıma
pcregrep -o "(?<=[)[^]]+(?=].*ERROR)" /var/log/app.log

pcregrep ile sed ve awk Kombinasyonu

pcregrep çıktısını diğer araçlarla birleştirince gerçek güç ortaya çıkıyor:

# Log'lardan hata kodlarını çıkar, frekans analizi yap
pcregrep -o "(?<=" )[45]d{2}(?= )" /var/log/nginx/access.log | 
    sort | uniq -c | sort -rn

# Çok satırlı blokları ayıkla, sadece belirli alanları raporla
pcregrep -M "TRANSACTION START.*nID: d+" transaction.log | 
    grep -oP "ID: Kd+"

# Config dosyasındaki enabled servisleri listele
pcregrep -M "^[service]n.*enableds*=s*true" services.conf | 
    grep -oP "(?<=[service-)w+"

Cron Job ve Monitoring Entegrasyonu

Günlük operasyonlarda pcregrepi cron job’larla entegre etmek çok işe yarıyor:

# /etc/cron.d/log-monitor
*/15 * * * * root 
    pcregrep -c 
    "(?i)(out of memory|killed process|oom killer)" 
    /var/log/syslog | 
    xargs -I{} test {} -gt 0 && 
    echo "OOM event tespit edildi" | 
    logger -t log-monitor -p user.crit

Daha kapsamlı bir monitoring scripti:

#!/bin/bash
# Servis sağlık kontrolü - pcregrep tabanlı

check_service_health() {
    local service_name="$1"
    local log_file="$2"
    local error_threshold="$3"

    # Son 100 satırda hata sayısını kontrol et
    local error_count
    error_count=$(tail -100 "$log_file" | 
        pcregrep -c "(?i)(error|exception|fatal|critical)")

    if [ "$error_count" -gt "$error_threshold" ]; then
        echo "UYARI: $service_name - Son 100 log satırında $error_count hata"
        # Son hatayı detaylı göster
        tail -100 "$log_file" | 
            pcregrep -M "(?i)(error|exception).*n(?:s+at .*n)*" | 
            tail -10
        return 1
    fi

    echo "OK: $service_name - $error_count hata (eşik: $error_threshold)"
    return 0
}

check_service_health "Tomcat" "/var/log/tomcat9/catalina.out" 5
check_service_health "PostgreSQL" "/var/log/postgresql/postgresql.log" 3
check_service_health "Nginx" "/var/log/nginx/error.log" 10

Sonuç

pcregrep her sysadmin’in araç kutusunda bulunması gereken bir araç. Standart grepten geçiş eğrisi oldukça düşük, ama kazanımlar çok büyük. Özellikle şu üç durumda pcregrepe geçmenizi kesinlikle öneririm:

  • Çok satırlı log bloklarını (stack trace, transaction kaydı, XML/JSON parçaları) analiz etmeniz gerektiğinde
  • Lookahead/lookbehind gibi gelişmiş regex özelliklerine ihtiyaç duyduğunuzda
  • Birden fazla karmaşık deseni tek seferde dosyadan okutarak tarama yapmanız gerektiğinde

Temel grep komutlarını biliyorsanız, pcregrepe adapte olmak için harcayacağınız bir iki saatlik pratik, ilerleyen haftalarda size onlarca saat kazandıracak. Production sorunlarını ayıklarken, güvenlik taramaları yaparken, ya da sadece bir config dosyasında karmaşık bir deseni ararken bu araç defalarca işinize yarayacak.

Son bir not: PCRE regex desenlerini test etmek için regex101.com sitesinde PCRE modunu seçerek desenlerinizi canlı olarak deneyebilirsiniz. Production’da çalıştırmadan önce bu adımı atlamayın.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir