İçeriğe geç
academia.sh

Ders 16 / 24

Akış Editörü ile Dönüştürme

Yerine koyma komutu ve bayrakları, geri başvurularla yeniden yazma, adres ve aralık seçimi, yerinde düzenlemenin gerçekleştirimler arasındaki uyumsuzluğu.

İçindekiler

Filtreleme satırları seçer ama değiştirmez. Kütükteki zaman damgasından yalnızca saati almak, sayısal kimlik içeren yolları tek bir kalıba indirmek ya da satırı ayrılmış bir kayda çevirmek için satırın kendisini dönüştürmek gerekir.

Akış editörü (stream editor), girdiyi satır satır okuyup her satıra bir komut dizisi uygulayan ve sonucu yazan süzgeçtir. Etkileşimli bir editörden farkı, kararların önceden verilmiş olmasıdır: dosya açılmaz, hiçbir şey görüntülenmez, akış yalnızca akar.

Yerine Koyma

En sık kullanılan komut s’dir: s/kalıp/yerine/bayraklar.

head -2 erisim.log | sed 's/HTTP\/1.1/HTTP/'
10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html HTTP" 200 5120
10.0.0.31 - - [07/Feb/2024:09:12:51 +0000] "GET /statik/stil.css HTTP" 200 2048

Kalıpta eğik çizgi geçtiği için kaçırılması gerekti. Ayırıcı serbesttir; s komutundan sonra gelen ilk karakter ayırıcı sayılır:

head -1 erisim.log | sed 's|HTTP/1.1|HTTP|'

Yol içeren kalıplarda | veya # seçmek, ters bölü yığılmasını ortadan kaldırır.

Öntanımlı davranış, her satırda yalnızca ilk eşleşmeyi değiştirmektir. Bayraklar bunu değiştirir:

echo 'a-b-c-d' | sed 's/-/+/'
echo 'a-b-c-d' | sed 's/-/+/g'
echo 'a-b-c-d' | sed 's/-/+/3'
a+b-c-d
a+b+c+d
a-b-c+d

g bayrağı tüm eşleşmeleri, sayı bayrağı yalnızca N‘inci eşleşmeyi değiştirir. I bayrağı büyük–küçük harf ayrımını kaldırır; POSIX’te tanımlı değildir ama yaygın gerçekleştirimlerde bulunur.

Eşleşen Metni Yeniden Kullanmak

Yerine koyma bölümünde & tüm eşleşmeyi temsil eder:

head -1 erisim.log | sed -E 's/ [0-9]{3} [0-9]+$/[&]/'
10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html HTTP/1.1"[ 200 5120]

Gruplar \1, \2 … ile geri çağrılır. Bu, satırı istenen biçimde yeniden yazmanın yoludur:

sed -E 's/^([0-9.]+) - - \[([^]]+)\] "([A-Z]+) ([^ ]+) [^"]*" ([0-9]{3}) ([0-9]+)$/\1|\3|\4|\5|\6/' erisim.log | head -3
10.0.0.12|GET|/index.html|200|5120
10.0.0.31|GET|/statik/stil.css|200|2048
10.0.0.12|GET|/urun/12|200|8410

Boşlukla ayrılmış ve tırnak içeren kütük satırı, boru işaretiyle ayrılmış beş alanlı bir kayda dönüştü. İkinci grup (zaman damgası) yakalandı ama kullanılmadı; yakalamak zorunludur, çünkü kalıp satırın tamamını kaplamalıdır.

Sözdizim Seçimi

sed öntanımlı olarak temel düzenli ifade sözdizimini kullanır. -E seçeneği genişletilmiş sözdizime geçer.

Temel sözdizimde bazı işleçlerin desteği gerçekleştirime bağlıdır:

echo 'aaa' | sed 's/a\+/X/'
echo 'aaa' | sed -E 's/a+/X/'
aaa
X

Birinci satırda hiçbir değişiklik olmadı: bu gerçekleştirim temel sözdizimde \+ işlecini tanımıyor, kalıbı “bir a ve bir artı işareti” diye okudu ve eşleşme bulamadı. GNU sürümünde aynı kalıp çalışır.

Sonuç: +, ?, | ve {n,m} kullanılacaksa -E yazılır. -E seçeneği hem BSD hem GNU sürümlerinde bulunur; eski GNU betiklerinde görülen -r seçeneği ise yalnızca GNU’ya özgüdür.

Adresler

Komutun önüne yazılan adres, komutun hangi satırlara uygulanacağını belirler.

Adres Anlamı
5 beşinci satır
$ son satır
/kalıp/ kalıba uyan satırlar
2,4 ikinci ile dördüncü satır arası
/a/,/b/ a eşleşen satırdan b eşleşene kadar
adres! adresin dışındaki satırlar

d komutu satırı siler. bir, iki, uc, dort satırlarını içeren bir dosyada:

sed '2,3d' s.txt
bir
dort
sed '$d' s.txt
bir
iki
uc
sed '/ik/d' s.txt
bir
uc
dort
sed '/ik/!d' s.txt
iki

! işareti seçimi tersine çevirir; son çağrı “eşleşmeyenleri sil” diyerek yalnızca eşleşeni bıraktı.

p komutu satırı yazar. Akış editörü öntanımlı olarak her satırı zaten yazdığı için p tek başına yineleme üretir; -n seçeneği öntanımlı yazımı kapatır ve p seçici hâle gelir:

sed -n '2,3p' s.txt
iki
uc

Bu ikili — -n ve p — filtrelemenin akış editörüyle yazılmış biçimidir. Yalnızca satır seçmek için süzgeç aracı daha uygundur; dönüştürme ile seçim birlikte gerekiyorsa akış editörü tek geçişte ikisini birden yapar.

Diğer Komutlar

y/abc/xyz/ karakter karşılıklarını dönüştürür; kalıp değil, birebir eşleme kullanır:

echo 'abc' | sed 'y/abc/xyz/'
xyz

q komutu, adresine ulaşıldığında akışı sonlandırır: sed '100q' ilk yüz satırı yazıp durur ve dosyanın kalanını okumaz.

Birden çok komut -e ile ya da noktalı virgülle zincirlenir:

head -1 erisim.log | sed -e 's/HTTP\/1.1//' -e 's/  */ /g'
10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html " 200 5120

Komutlar her satıra sırayla uygulanır; ikinci komut, birincinin çıktısı üzerinde çalışır. Bu, bir yerine koymanın diğerini besleyebileceği anlamına gelir ve sıra değiştiğinde sonuç değişir.

Yerinde Düzenleme: Taşınabilir Değil

-i seçeneği dosyayı yerinde değiştirir. Bu seçeneğin argüman alışı iki büyük gerçekleştirimde uyumsuzdur ve bu, kabuk betiklerindeki en yaygın taşınabilirlik hatalarından biridir.

BSD sürümünde -i zorunlu olarak bir yedek soneki argümanı ister:

sed -i 's/bir/BIR/' s.txt
sed: 1: "s.txt
": unterminated substitute pattern

Seçenek, ardından gelen s/bir/BIR/ dizisini yedek soneki sandı ve s.txt adını komut olarak ayrıştırmaya çalıştı. Doğru yazım boş soneki açıkça vermektir:

sed -i '' 's/bir/BIR/' s.txt

GNU sürümünde ise sone seçeneğe bitişik yazılır; ayrı bir boş argüman verilirse dosya adı sanılır:

sed -i '' 's/bir/BIR/' s.txt
sed: can't read s/bir/BIR/: No such file or directory

İki yazımdan hiçbiri her iki sürümde çalışmaz. Betiklerde -i kullanmamak, taşınabilirlik gereken her durumda doğru karardır. Yerine, Yönlendirme dersinde kurulan desen yazılır:

sed 's/bir/BIR/' s.txt > s.yeni && mv s.yeni s.txt

Bu desen üç üstünlük taşır: her yerde aynı çalışır, sed başarısız olursa özgün dosya bozulmaz ve mv aynı dosya sisteminde atomiktir — dosyayı okuyan başka bir süreç ya eski ya yeni içeriği görür, yarım hâlini değil.

-i seçeneğinin kendisi de bunu yapar: geçici dosyaya yazıp yer değiştirir. Sağladığı tek şey yazım kısalığıdır ve bedeli taşınabilirliktir.

Betiğe Uygulama

Kütükteki yolların bir bölümü sayısal kimlik içeriyor: /urun/12 ve /urun/45 ayrı ayrı sayıldığında ikisi de listenin altında kalır. Kimlikleri tek bir simgeye indirmek, hangi uç noktanın yoğun olduğunu görünür kılar:

kutuk=erisim.log

cut -d' ' -f7 "$kutuk" | sed -E 's#/[0-9]+#/:id#g' | sort | uniq -c | sort -rn
   6 /urun/:id
   6 /api/veri
   4 /yok.html
   4 /index.html
   3 /statik/stil.css
   3 /panel
   2 /gizli
   1 /giris
   1 /eski-sayfa

/urun/:id altı istekle listenin başına çıktı; ayrı sayıldığında üçer istekle dördüncü ve beşinci sıradaydı. Normalleştirme, sayımın neyi ölçtüğünü değiştirir — bu bir biçim düzeltmesi değil, çözümleme kararıdır ve rapor çıktısında belirtilmelidir.

İkinci uygulama, zaman damgasından saat alanını çıkarır:

sed -E 's/^.*:([0-9]{2}):[0-9]{2}:[0-9]{2} .*$/\1/' "$kutuk" | sort | uniq -c
  30 09

Örnek kütüğün tamamı tek bir saat dilimine düştüğü için tek satır çıktı; günlere yayılan gerçek bir kütükte bu, yük dağılımını veren bir sütun üretir.

Kalıptaki ^.*: bölümü açgözlüdür ve son iki nokta üst üsteye kadar ilerler; sonraki gruplar bu yüzden dakika ve saniyeyi eşler. Açgözlülüğün burada işe yaraması rastlantı değildir, ama kalıbın doğruluğu ona bağlıdır — açgözlülüğe dayanan kalıplar kırılgandır ve alan tabanlı bir çözüm daha güvenlidir.

Özet

  • Yerine koyma s/kalıp/yerine/bayrak biçimindedir; ayırıcı serbesttir ve öntanımlı davranış satır başına bir eşleşmedir.
  • & tüm eşleşmeyi, \1, \2 grupları temsil eder; satırı yeniden yazmanın aracı budur.
  • Temel sözdizimde \+ gibi işleçlerin desteği gerçekleştirime bağlıdır; -E her iki yaygın sürümde bulunur ve yeğlenir.
  • Adres komutun kapsamını belirler; ! seçimi tersine çevirir, -n ile p seçici yazma sağlar.
  • -i seçeneğinin argüman alışı BSD ve GNU sürümlerinde uyumsuzdur; taşınabilir yazım geçici dosyaya yazıp yer değiştirmektir.

Sonraki Adım

Akış editörü satırı bir metin olarak görür; alanları ancak kalıpla taklit edebilir. Kütük gibi sütunlu verilerde bu, kırılgan kalıplara yol açar. Sonraki ders alan tabanlı işlemeyi ele alır: satırı otomatik olarak alanlara bölen, alanlar üzerinde hesap yapabilen ve anahtar başına birikim tutabilen aracı — böylece önceki konuda ilişkisel dizilerle yazılan sayımlar tek satıra inecek.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat