İçeriğe geç
academia.sh

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:

  1. Eşleşmesi istenen satırlardan birini alın ve harfi harfine arayın.
  2. Değişken bölümleri sırayla sınıf ve yineleyiciyle değiştirin; her adımda grep -c ile eşleşme sayısını gözleyin.
  3. Sayı beklenenden büyükse kalıp fazla geniştir; küçükse bir durumu kaçırıyordur.
  4. Kalıbı -o ile çalıştırıp eşleşen bölümü gözle doğrulayın.
  5. 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; \d gibi 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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat