grep, sed ve awk: Linux terminalinde metin işleme örnekleri
grep satırları desene göre bulur (grep -rn error /var/log), sed akıştaki veya dosyadaki metni değiştirir (sed -i 's/eski/yeni/g' dosya), awk sütunlarla çalışır ve sayım yapar (awk '{print $1}' access.log). Birlikte bir boru hattında kullanıldığında grep satırları süzer, sed metni düzeltir, awk alanları ayıklayıp toplar.
grep, sed ve awk, Linux'ta metin işlemek için kullanılan üç klasik araçtır. grep desene uyan satırları bulur, sed akıştaki metni değiştirir veya siler, editör açmadan çalışır, awk ise satırı sütunlara ayırır ve hesap yapabilir. Aşağıda log dosyalarını, yapılandırma dosyalarını ve komut çıktılarını incelerken gerçekten işinize yarayacak grep sed awk örneklerini ve sık yapılan hataları bulacaksınız.
Ne zaman hangisini kullanmalı
Üç araç da metni satır satır okur ve sonucu standart çıktıya yazar; bu yüzden | ile kolayca birbirine bağlanırlar. Aralarındaki fark, her birinin en iyi çözdüğü iştedir.
| Görev | Araç | Örnek |
|---|---|---|
| Metin içeren satırları bulmak | grep | grep ERROR app.log |
| Metni değiştirmek | sed | sed 's/http:/https:/g' file |
| Satırları numarasıyla silmek veya göstermek | sed | sed -n '10,20p' file |
| Bir sütunu almak | awk | awk '{print $1}' access.log |
| Toplam, ortalama, gruplama hesaplamak | awk | awk '{s+=$10} END {print s}' |
Basit bir kural: yalnızca süzmek istiyorsanız grep, metni değiştirmek istiyorsanız sed, metinde sütun varsa veya aritmetik gerekiyorsa awk kullanın.
grep: desene göre satır arama
Temel grep örnekleri
# Dosyada error kelimesi geçen satırlar
grep error /var/log/syslog
# Büyük/küçük harf duyarsız: Error, ERROR, error
grep -i error app.log
# Satır numaralarıyla
grep -n "Connection refused" app.log
# Dizinde özyinelemeli arama, dosya adlarıyla
grep -rn "DB_HOST" /etc/myapp/
# Yalnızca eşleşme bulunan dosya adları
grep -rl "TODO" src/
# Tersine çevirme: yorumlar ve boş satırlar HARİÇ her şey
grep -v -e '^#' -e '^$' /etc/ssh/sshd_config
# Eşleşen satır sayısını saymak
grep -c " 500 " access.log
-w bayrağı kelimeyi tam olarak arar: grep -w log, login kelimesini bulmaz. -F bayrağı düzenli ifadeleri kapatır ve dizeyi olduğu gibi arar; desende nokta, parantez veya yıldız varsa bu kullanışlıdır.
Bulunan satırın çevresi
Bir hatayı tek satıra bakarak anlamak nadiren mümkündür; ona yol açan yığın izi veya sorguya ihtiyaç duyarsınız. Bunun için bağlam bayrakları vardır:
# Eşleşmeden sonraki 3 satır (After)
grep -A 3 "Traceback" app.log
# Eşleşmeden önceki 2 satır (Before)
grep -B 2 "OOM" /var/log/kern.log
# Her iki yanda 5 satır (Context)
grep -C 5 "segfault" /var/log/syslog
grep, eşleşme gruplarını -- satırıyla ayırır; böylece çıktıyı gözle okumak kolaylaşır.
grep ve düzenli ifadeler
grep varsayılan olarak temel düzenli ifadeleri (BRE) anlar. -E bayrağıyla genişletilmiş ifadeler (ERE) açılır; burada +, ?, | ve parantezler ters eğik çizgi olmadan çalışır.
| Yapı | Anlamı | Örnek |
|---|---|---|
^ | satırın başı | grep '^root' /etc/passwd |
$ | satırın sonu | grep 'bash$' /etc/passwd |
. | herhangi bir karakter | grep 'h.t' |
* | 0 veya daha fazla tekrar | grep 'ab*c' |
+ (ERE) | 1 veya daha fazla | grep -E '[0-9]+' |
| (ERE) | veya | grep -E 'error|warn' |
[...] | verilen kümeden bir karakter | grep '[Ee]rror' |
# Hata veya uyarı içeren satırlar
grep -E "ERROR|WARN" app.log
# Logdaki yalnızca IP adresleri, her satırda bir tane (-o — yalnızca eşleşmeyi yazdır)
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' access.log
grep -P: bilinen parçalar arasındaki değeri almak
GNU grep'te Perl tarzı düzenli ifadeler için -P bayrağı vardır. Bununla \K (“bu noktaya kadar eşleşen her şeyi unut”) ve ileriye bakış kullanılabilir; böylece yalnızca değer alınır:
$ echo 'user_id=4821 status=ok' | grep -oP 'user_id=\K[0-9]+'
4821
$ grep -oP '"version":\s*"\K[^"]+' package.json
2.4.1
-P bayrağı her grep sürümünde yoktur (örneğin macOS'taki BSD grep'te yoktur), bu yüzden taşınabilir betiklerde sed veya awk kullanmak daha iyidir.
Betik koşullarında grep -q
grep -q hiçbir şey yazdırmaz, yalnızca çıkış kodunu döndürür: 0 bulundu, 1 bulunamadı. Bu sayede kontrolü doğrudan if içine yazabilirsiniz:
if grep -q "^PermitRootLogin no" /etc/ssh/sshd_config; then
echo "root girişi kapalı"
fi
Bu, çıktıyı bir değişkene alıp boş olup olmadığını kontrol etmekten daha kısadır; ayrıca grep ilk eşleşmede durur.
sed: metni değiştirme ve silme
Değiştirme: s komutu
sed'in temel komutu s/desen/yerine/bayraklar biçimindedir. g bayrağı yoksa her satırda yalnızca ilk eşleşme değişir.
# Metni değiştirilmiş olarak yazdır (dosya değişmez)
sed 's/foo/bar/' file.txt
# Satırdaki tüm geçişleri değiştir
sed 's/foo/bar/g' file.txt
# Büyük/küçük harf duyarsız (GNU sed)
sed 's/error/ERROR/gI' app.log
# Metinde eğik çizgi varsa farklı ayraç kullan
sed 's|/var/www|/srv/www|g' nginx.conf
sed -i: dosyanın içinde değiştirme
-i bayrağı sonucu dosyaya geri yazar. Orijinali kaybetmemek için yedek eki verin:
# config.ini.bak oluşturur ve config.ini'yi değiştirir
sed -i.bak 's/^debug=true/debug=false/' config.ini
# Dizindeki tüm .conf dosyalarında değiştirme
find /etc/myapp -name "*.conf" -exec sed -i 's/old-host/new-host/g' {} +
Toplu düzenlemeden önce komutu -i olmadan çalıştırıp çıktıya bakın. macOS'taki BSD sed'de -i zorunlu bir argüman ister: sed -i '' 's/a/b/' file.
Satırları numara ve desene göre işlemek
# 10–20. satırları göster (-n otomatik yazdırmayı kapatır, p — yazdır)
sed -n '10,20p' file.txt
# 5. satırı sil
sed '5d' file.txt
# Son satırı sil
sed '$d' file.txt
# Boş satırları ve yorumları sil
sed -e '/^$/d' -e '/^#/d' nginx.conf
# Yalnızca "listen" içeren satırlarda değiştir
sed '/listen/s/80/8080/' nginx.conf
# Eşleşmeden sonra satır ekle (GNU sed)
sed '/^\[mysqld\]/a max_connections = 500' my.cnf
Geri referanslar ve &
Desenin parantez içindeki parçası \1, \2 ile yerine konabilir; & karakteri ise bulunan metnin tamamını temsil eder.
# Ad ve soyadı yer değiştir (-E ile ERE)
$ echo "Иванов Пётр" | sed -E 's/(\S+) (\S+)/\2 \1/'
Пётр Иванов
# Tüm sayıları köşeli parantez içine al
$ echo "port 8080, timeout 30" | sed -E 's/[0-9]+/[&]/g'
port [8080], timeout [30]
# 2026-10-14 tarihini 14.10.2026 yap
$ echo 2026-10-14 | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3.\2.\1/'
14.10.2026
awk: sütunlar, koşullar ve hesaplar
Gerekli sütunu yazdırma
awk her satırı boşluk ve sekme karakterlerine göre alanlara böler: $1 birinci alan, $2 ikinci, $NF son alan, $0 ise tüm satırdır.
# nginx logundan IP adresleri (ilk sütun)
awk '{print $1}' /var/log/nginx/access.log
# /etc/passwd'den kullanıcı adı ve kabuk (ayraç iki nokta)
awk -F: '{print $1, $7}' /etc/passwd
# Son sütun
df -h | awk '{print $NF}'
# Çıktıda kendi ayracınızı kullanın
awk -F: -v OFS=';' '{print $1, $3}' /etc/passwd
Koşullar: yalnızca gerekli satırları yazdırma
Süslü parantezlerden önce bir koşul yazabilirsiniz; awk eylemi yalnızca uygun satırlarda çalıştırır.
# UID değeri 1000 ve üstü olan kullanıcılar (sistem değil, normal kullanıcılar)
awk -F: '$3 >= 1000 {print $1}' /etc/passwd
# Yanıt kodu 500 ve üstü olan istekler (combined biçimde 9. alan)
awk '$9 >= 500' access.log
# 6. sütun düzenli ifadeyle eşleşen satırlar
awk '$6 ~ /POST/' access.log
# ls -l çıktısından 100 MB'tan büyük dosyalar
ls -l | awk '$5 > 100*1024*1024 {print $9}'
BEGIN, END ve NR: awk ile küçük bir program
BEGIN bloğu ilk satır okunmadan önce, END bloğu son satırdan sonra çalışır. NR geçerli satır numarasını tutar; END bloğunda ise toplam satır sayısını verir.
# Yanıt boyutlarının (10. alan) toplamı, megabayt olarak
awk '{sum += $10} END {printf "%.1f MB\n", sum/1024/1024}' access.log
# Son sütundaki yanıt süresinin ortalaması
awk '{s += $NF} END {if (NR) print s/NR}' timings.log
# CSV başlığını atla
awk -F, 'NR > 1 {print $2}' users.csv
# IP'ye göre istek sayımı: ilişkisel dizi
awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' access.log | sort -rn | head
Son örnek log analizinin klasik yöntemidir: count dizisi, anahtar olarak IP ile sort | uniq -c ikilisinin yerini alır ve her IP için trafik toplamı gibi ek hesaplara kolayca genişletilebilir.
Boru hatları: grep, sed ve awk birlikte
Asıl güç birleştirmededir. Her araç kendi işini yapar, | sonucu bir sonrakine aktarır.
5xx hatası veren ilk 10 IP
grep ' 50[0-9] ' /var/log/nginx/access.log \
| awk '{print $1}' \
| sort | uniq -c | sort -rn | head -10
412 203.0.113.45
118 198.51.100.7
36 192.0.2.19
Burada grep satırları kabaca eler, awk alanı ayırır, sort | uniq -c tekrarları sayar. Aynısını tek bir awk ile de yazabilirsiniz: awk '$9 ~ /^5/ {c[$1]++} END {for (i in c) print c[i], i}' access.log | sort -rn | head. Bu yöntem daha doğrudur, çünkü yanıt kodunun bulunduğu sütun doğrudan kontrol edilir.
En sık açılan URL'ler
awk '{print $7}' access.log | sed 's/?.*//' | sort | uniq -c | sort -rn | head
Burada sed, sorgu dizesini kırpar; böylece /search?q=a ve /search?q=b tek sayfa olarak sayılır.
Yorumsuz yapılandırmadan değerler
grep -v '^\s*#' /etc/myapp/app.env | grep '=' | awk -F= '{print $1}'
Belirli bir saatteki hatalar
grep '14/Oct/2026:03:' access.log | awk '$9 >= 500 {print $4, $7, $9}'
Sık yapılan hatalar
- awk için tek tırnak yerine çift tırnak kullanmak.
awk "{print $1}"yazarsanız kabuk, awk çalışmadan önce kendi$1değişkenini yerleştirir. awk programını ve sed ifadelerini tek tırnak içine yazın. - sed'de
gbayrağını unutmak. Bu bayrak olmadan satırdaki yalnızca ilk eşleşme değişir, diğerleri kalır. - Kontrol etmeden
sed -ikullanmak. Hatalı bir düzenli ifade dosyayı sessizce bozar. Önce-iolmadan çalıştırın veya-i.bakkullanın. - grep'te
+ve|çalışmıyor. Bunlar genişletilmiş sözdizimidir:grep -E(veyased -E) gerekir. - Desendeki nokta.
grep 192.168.1.1192x168y1z1satırını da bulur, çünkü nokta “herhangi bir karakter” demektir.grep -Fkullanın veya\.ile kaçış yapın. - Sütunlarda boşluklar. Alan boşluk içerebiliyorsa (CSV, yol), ayracı açıkça belirtin:
awk -F,veyaawk -F'\t'. - Gereksiz cat.
cat file | grep xde çalışır, amagrep x filedaha kısadır ve fazladan süreç açmaz.
grep, sed ve awk yerine ne kullanılabilir
JSON için bu araçlar uygun değildir: yapıyı jq ile (jq '.items[] | select(.status=="active") | .name'), YAML için ise yq ile okumak daha iyidir. Büyük projelerde hızlı özyinelemeli arama için çoğu zaman ripgrep (rg komutu) kullanılır; varsayılan olarak .gitignore dosyasına uyar. Perl sözdizimini tercih ediyorsanız, perl -pe 's/a/b/g' ve perl -lane 'print $F[0]' tek satırda sed ve awk'ın yerini alır. Ancak grep, sed ve awk neredeyse her sunucuda kurulum gerektirmeden bulunur; bu yüzden önce onları öğrenmek gerekir.
Özet
grep satırları bulur, sed onları değiştirir, awk sütunlarla çalışır ve sayım yapar. Temel setinizi aklınızda tutun: grep -rniE ile -A/-B/-C, sed 's/.../.../g' ile -i.bak ve -n 'Np', awk -F ile $1, $NF, koşullar ve END bloğu. Neredeyse her log analizi bu parçalardan oluşur. Bu grep sed awk örneklerini find, jq ve curl ile birlikte, Linux kursunun terminalde metin işleme dersinde uygulamalı olarak ele alıyoruz.
Sık sorulan sorular
grep ile egrep arasındaki fark nedir?
egrep, grep -E için eski bir takma addır (genişletilmiş düzenli ifadeler). Modern GNU grep, egrep çağrıldığında uyarı verir; bu yüzden grep -E yazın.
Bir dizindeki tüm dosyalarda metin nasıl aranır?
grep -rn "metin" /yol kullanın: -r özyinelemeli arar, -n satır numarasını gösterir. Dosya türünü sınırlamak için --include="*.php" ekleyin.
Birçok dosyada metin nasıl değiştirilir?
Aramayı sed ile birleştirin: grep -rl "eski" . | xargs sed -i 's/eski/yeni/g'. Önce commit yapmak veya yedek almak iyi bir fikirdir.
awk'ta birden fazla sütun sekmeyle nasıl yazdırılır?
Çıktı ayracını belirleyin: awk -v OFS='\t' '{print $1, $3}' file. OFS verilmezse alanlar boşlukla ayrılır.
sed ile satır sonlarındaki boşluklar nasıl silinir?
sed -i 's/[[:space:]]*$//' file komutu, dosyadaki tüm satırların sonundaki boşluk ve sekmeleri siler.
Bu konu “Linux: с нуля до уверенного администрирования” kursunda uygulamalı olarak ayrıntılı işleniyor.
Kursa git