Ders 14 / 24
Düzenli İfadeler
Temel ve genişletilmiş sözdizim ayrımı, yineleyiciler, çapa ve köşeli ayraç ifadeleri, açgözlülük ve taşınabilir karakter sınıfları.
İçindekiler
Betik şu ana dek yolları cut ile ayırdı ve durum kodlarını sabit dizgilerle saydı. İki
yaklaşım da verinin biçiminin kusursuz olduğunu varsayar. Gerçek kütüklerde bozuk satır,
eksik alan ve beklenmedik biçim bulunur; ayrıca “dört yüz ile başlayan kodlar” gibi
kalıplar sabit dizgiyle ifade edilemez.
Düzenli ifade (regular expression), bir dizgi kümesini betimleyen kalıp dilidir. Algoritmalar kursunun metin algoritmaları konusunda örüntü arama sabit bir dizgi için tanımlanmıştı; düzenli ifade aynı problemi bir dizgi yerine sonsuz olabilen bir küme için kurar.
Bu ders kalıp dilini kurar. Sonraki dersler onu araçlara bağlar.
İki Sözdizim
POSIX iki düzenli ifade sözdizimi tanımlar ve araçlar hangisini kullandığını seçenekle bildirir.
Temel düzenli ifade (basic regular expression, BRE), grep ve sed komutlarının
öntanımlı sözdizimidir. Gruplama, seçenek ve bazı yineleyiciler ters bölüyle yazılır.
Genişletilmiş düzenli ifade (extended regular expression, ERE), grep -E ve awk
tarafından kullanılır. Aynı işleçler ters bölüsüz yazılır.
grep -c '\(404\|500\)' erisim.log grep -Ec '(404|500)' erisim.log
7 7
İki kalıp aynı kümeyi betimler; yalnızca yazımları farklıdır. Bu kursta ERE yeğlenecek: okunması daha kolaydır ve ters bölü yığılmasını önler.
Kalıplar tek tırnak içinde yazılır. Kalıp dilindeki $, *, \, [ karakterleri
kabuk için de anlamlıdır; tek tırnak bunların kabuk tarafından yorumlanmasını engeller.
Bu, Değişkenler ve Tırnak Kuralları dersindeki kuralın doğrudan uygulanmasıdır.
Harfi Harfine Eşleşme ve Nokta
Özel anlamı olmayan her karakter kendisiyle eşleşir. . ise herhangi bir tek
karakterle eşleşir — bu, en sık gözden kaçan özel karakterdir.
printf '%s\n' 'stil.css' 'stilXcss' 'stil-css' > adlar.txt grep 'stil.css' adlar.txt
stil.css stilXcss stil-css
Nokta kaçırılınca yalnızca gerçek nokta eşleşir:
grep 'stil\.css' adlar.txt
stil.css
Dosya adı, alan adı ve IP adresi gibi nokta içeren verilerde bu ayrım doğruluk meselesidir.
Yineleyiciler
Yineleyici, kendinden önceki öğenin kaç kez tekrarlanacağını belirtir.
| ERE | BRE | Anlamı |
|---|---|---|
* |
* |
sıfır veya daha çok |
+ |
\+ |
bir veya daha çok |
? |
\? |
sıfır veya bir |
|
\{n\} |
tam olarak n |
{n,m} |
\{n,m\} |
en az n, en çok m |
printf '%s\n' 'renk' 'renkk' 'renkkk' > yin.txt
grep -Ec 'renk+' yin.txt grep -Ec 'renk{2}' yin.txt grep -Ec 'renk{1,2}' yin.txt
3 2 3
renk{2} iki satırda eşleşti: renkk ve renkkk — ikincisinde ilk iki k yeterlidir,
çünkü kalıbın satırın tamamını kaplaması gerekmez.
Bu son cümle kritiktir. Düzenli ifade, satırın herhangi bir yerinde eşleşme arar. Tam satır eşleşmesi isteniyorsa çapa kullanılır.
Çapalar
^ satırın başını, $ satırın sonunu belirtir. İkisi de karakter değil konum
eşler; genişlikleri yoktur.
grep -c '^10\.0\.0' erisim.log
14
İkisi birlikte kullanıldığında kalıp satırın tamamını kaplar. Kütükteki her satırın beklenen biçimde olduğunu doğrulamak bu yolla yapılır:
KALIP='^[0-9.]+ - - \[[^]]+\] "[A-Z]+ [^ ]+ HTTP/[0-9.]+" [0-9]{3} [0-9]+$' grep -Ec "$KALIP" erisim.log
30
Otuz satırın tamamı kalıba uydu. Kütüğe bozuk satırlar karıştığında -v seçeneği onları
ayıklar:
{ cat erisim.log
echo 'bozuk satir'
echo '10.0.0.1 - - [x] "GET /a HTTP/1.1" 200 5'
} > tumu.log
grep -Ev "$KALIP" tumu.log
bozuk satir
İki bozuk satır eklendi ama kalıp yalnızca birini yakaladı. İkincisinin zaman damgası
gerçekçi değil, buna karşın \[[^]]+\] parçası “köşeli ayraçlar arasında en az bir
karakter” dediği için kalıba uyuyor. Kalıp, betimlediği kadarını doğrular; alan sayısına
dayanan tamamlayıcı bir sınama Alan Tabanlı İşleme dersinde eklenecek.
Bu kalıp değişkende tutulduğu için çift tırnakla genişletilmiştir; tek tırnak kullanılsaydı değişken adı harfi harfine geçerdi. Kalıbın kendisi atama sırasında tek tırnak içindeydi.
Köşeli Ayraç İfadeleri
Köşeli ayraç, bir karakter kümesi tanımlar ve içindeki tüm karakterlerden birini eşler.
[abc]— üç harften biri[0-9]— aralık[^0-9]— kümede olmayan (değilleme)[.-]— köşeli ayraç içinde çoğu özel karakter anlamını yitirir
cut -d' ' -f9 erisim.log | grep -c '^[^2]' cut -d' ' -f9 erisim.log | grep -Ec '^[45]'
12 9
Otuz istekten on ikisi başarı sınıfı dışında, dokuzu hata sınıfındadır.
Değilleme yalnızca ayracın ilk konumunda özel anlam taşır; [a^b] üç karakterden
birini eşler. Kısa çizgi de aynı kuraldadır: son konumdaysa harfi harfinedir.
Taşınabilir Karakter Sınıfları
POSIX, adlandırılmış karakter sınıfları tanımlar. Köşeli ayraç içinde yazılırlar ve kendileri de ayraçlıdır:
| Sınıf | Karşılığı |
|---|---|
[[:digit:]] |
rakamlar |
[[:alpha:]] |
harfler |
[[:alnum:]] |
harf ve rakamlar |
[[:space:]] |
boşluk türleri |
[[:upper:]], [[:lower:]] |
büyük ve küçük harfler |
grep -Eo '^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+' erisim.log | sort -u
10.0.0.12 10.0.0.31 10.0.2.7 172.16.0.9 192.168.1.5
-o seçeneği satırın tamamını değil, yalnızca eşleşen bölümü yazar.
Bazı gerçekleştirimler \d, \w, \s gibi kısayollar sunar. Bunlar POSIX’te tanımlı
değildir; destekleyen ve desteklemeyen araçlar birlikte bulunur. Aynı kalıbı iki farklı
sistemde çalıştırdığınızda farklı sonuç almanın en yaygın nedeni budur. Taşınabilir
betikte [[:digit:]] yazılır.
Adlandırılmış sınıfların ikinci üstünlüğü, [a-z] gibi aralıkların yerel ayara bağlı
olmasıdır: sıralama düzeni değiştiğinde aralığın kapsadığı karakterler de değişir.
[[:lower:]] bu belirsizliği taşımaz.
Açgözlülük
Yineleyiciler açgözlüdür (greedy): eşleşebilecekleri en uzun metni alırlar.
echo 'a"bir" ve "iki"z' | grep -Eo '".*"' echo 'a"bir" ve "iki"z' | grep -Eo '"[^"]*"'
"bir" ve "iki" "bir" "iki"
İlk kalıptaki .*, iki tırnak arasındaki her şeyi yuttu. İkinci kalıp [^"]* yazımıyla
“tırnak olmayan karakterler” dediği için her alıntıyı ayrı eşledi.
POSIX düzenli ifadelerinde açgözlü olmayan yineleyici (*? gibi) yoktur. Çözüm her
zaman aynıdır: sınırlayıcıyı değilleyen bir karakter sınıfı kullanmak. Bu kalıp — açılış
sınırlayıcı, sınırlayıcı olmayanların yinelenmesi, kapanış sınırlayıcı — alan ayıklamanın
temel biçimidir ve kütükteki köşeli ayraçlı zaman damgasını almak için de kullanılır.
Gruplama ve Geri Başvuru
Parantez bir alt kalıbı gruplar; hem yineleyici uygulamak hem de eşleşen metni saklamak
için kullanılır. \1, \2 … saklanan metne geri başvurur (backreference).
printf '%s\n' 'aa' 'ab' 'abab' > tekrar.txt grep -E '(.)\1' tekrar.txt grep -E '(..)\1' tekrar.txt
aa abab
Birinci kalıp “aynı karakterin iki kez yinelenmesi”ni, ikincisi “aynı iki karakterin iki kez yinelenmesi”ni betimler. Geri başvuru, düzenli ifadelerin biçimsel dil kuramındaki tanımının ötesine geçtiği noktadır: geri başvurulu kalıplar düzenli dil sınıfını aşar ve eşleştirme maliyeti üstel olabilir.
Grupların asıl kullanımı, eşleşen bölümleri yerine koymadır; bu, Akış Editörü ile Dönüştürme dersinde ele alınacak.
Kalıp Yazma Yöntemi
Karmaşık kalıplar tek seferde yazılmaz. İzlenecek sıra şudur:
- Eşleşmesi istenen satırlardan birini alın ve harfi harfine arayın.
- Değişken bölümleri sırayla sınıf ve yineleyiciyle değiştirin; her adımda
grep -cile eşleşme sayısını gözleyin. - Sayı beklenenden büyükse kalıp fazla geniştir; küçükse bir durumu kaçırıyordur.
- Kalıbı
-oile çalıştırıp eşleşen bölümü gözle doğrulayın. - Son adımda çapa ekleyip tam satır eşleşmesine geçin.
Yukarıdaki satır doğrulama kalıbı bu yolla kurulmuştur. Her adımda ölçülebilir bir sayı üretmek, kalıbı sınamanın en ucuz yoludur.
Özet
- Düzenli ifade bir dizgi kümesini betimler; POSIX iki sözdizim tanımlar ve araçlar hangisini kullandığını seçenekle bildirir.
- Kalıplar tek tırnak içinde yazılır;
.herhangi bir karakteri eşler ve gerçek nokta için kaçırılmalıdır. - Kalıp satırın herhangi bir yerinde eşleşir; tam satır eşleşmesi
^ve$çapalarıyla kurulur. - Adlandırılmış karakter sınıfları taşınabilirdir ve yerel ayardan etkilenmez;
\dgibi kısayollar POSIX’te tanımlı değildir. - Yineleyiciler açgözlüdür ve POSIX’te açgözlü olmayan biçim yoktur; çözüm sınırlayıcıyı değilleyen karakter sınıfıdır.
Sonraki Adım
Kalıp dili kuruldu; şimdi onu bir araca bağlamak gerekiyor. Sonraki ders satır
filtrelemeyi ele alır: eşleşen satırları seçmenin ötesinde saymak, tersini almak, yalnızca
eşleşen bölümü yazmak, dosya adlarını listelemek ve grep’in çıkış kodunu bir koşul
olarak kullanmak.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.