Dizgiler
Önceki
İçindekiler
İçindekiler
Diziler
Sonraki

 Ruby Kullanıcı KılavuzuDüzenli İfadeler 

Şimdi daha ilginç bir program yazalım. Bu sefer verilen bir dizginin istenen bir şablona uyup uymadığına bakalım:

Bu şablonlarda karakterler ve karakter kombinasyonları bulunur:

[] aralık belirlemek için kullanılır (örneğin, [a-z], a ile z arasındaki harfleri belirtir)
\w rakam ya da harf, [0-9A-Za-z] ile aynı
\W rakam ya da harf değil
\s boşluk karakteri; [ \t\n\r\f] ile aynı
\S boşluk-harici karakter
\d boşluk karakteri; [0-9] ile aynı
\D rakam- harici
\b backspace (0x08) (sadece herhangi bir aralık belirtilmişse)
\b kelime sınırlaması (eğer herhangi bir aralık belirtmesi yoksa)
\B kelime sınırlaması
* sıfır ya da daha fazla tekrarlama
+ bir ya da daha fazla tekrarlama
{m,n} n az m en çok n kez tekrarlama
? en fazla bir kere tekrarlama {0,1}ile aynı
| uyabilecek sonraki ifade
() gruplama

Bu ilginç lügat genelde düzenli ifadeler olarak anılır. Ruby'de, Perl'de de olduğu gibi çift tırnak koymak yerine ters bölü işareti kullanılır. Eğer daha önce düzenli ifadelerle karşılaşmadıysanız muhtemelen düzenli hiç birşey göremeyeceksiniz ancak alışmak için biraz zamana ihtiyacınız olduğunu unutmayın. Düzenli ifadeler, metin dizgileri üzerinde arama, eşleştirme ve bu gibi diğer işlerle uğraşırken sizi baş ağrısından (ve satırlarca koddan) kurtaran gözle görülür bir güce sahiptir.

Örneğin aşağıdaki tanıma uyan bir dizgi aradığımızı farzedelim: "Küçük f harfiyle başlayan, ardından bir büyük harfle devam eden bundan sonra küçük harf haricinde herhangi bir karakterle devam eden" bir dizgi. Eğer deneyimli bir C programcısıysanız muhtemelen şimdiden kafanızca binlerce satır kod yazmıştınız, öyle değil mi? Kabul edin, kendinize güçlükle yardım edebilirsiniz. Anck Ruby'de sadece dizgiyi şu düzenli ifadeyle test etmeniz yeterli olacaktır: /^f[A-Z](^[a-z])*$/.

Köşeli parantezler içindeki bir onaltılık sayıya ne dersiniz? Hiç sorun değil.

ruby> def chab(s)   # "koseli parantezler arasında hex rakam icerir"
    |    (s =~ /<0(x|X)(\d|[a-f]|[A-F])+>/) != nil
    | end
  nil
ruby> chab "Bu degil."
  false
ruby> chab "Bu olabilir mi? {0x35}"    # yanlis parantez tipi
  false
ruby> chab "Ya da bu? <0x38z7e>"    # bogus hex rakami
  false
ruby> chab "Peki bu: <0xfc0004>."
  true

Düzenli ifadeler başlangıçta bulmacalı gibi gözükse de kısa süre içinde istediğinizi yapabilme konusunda yol katedeceksiniz.

Aşağıda düzenli ifadeleri anlamanıza yarayacak küçük bir program bulunuyor. regx.rb olarak kaydedin ve komut satırına "ruby regx.rb" yazarak çalıştırın.

#ANSI terminal gerektirir!

st = "\033[7m"
en = "\033[m"

while TRUE
  print "str> "
  STDOUT.flush
  str = gets
  break if not str
  str.chop!
  print "pat> "
  STDOUT.flush
  re = gets
  break if not re
  re.chop!
  str.gsub! re, "#{st}\\&#{en}"
  print str, "\n"
end
print "\n"

Program bir tanesi dizgi diğeri de düzenli ifade olmak üzere iki girdi alır. Dizgi verilen düzenli ifade ile test edilir ve bütün uyuşan sonuçlar listelenir. Şu an ayrıntılara ilgilenmeyin, bu kodun analizini daha sonra yapacağız.

str> foobar
pat> ^fo+
foobar
~~~

Programın çıktısında ne görüyorsunuz? "~~~" satırları metin- tabanlı tarayıcılara özgüdür.

Bir kaç girdi daha deneyelim.

str> abc012dbcd555
pat> \d
abc012dbcd555
   ~~~    ~~~

Eğer şaşırdıysanız sayfanın başındaki tabloya tekrar göz atabilirsiniz: \d'nin d karakteriyle hiçbir bağlantısı yoktur ancak bir rakamı eşleştirmekte kullanılır.

Eğer istediğimiz kriterlere uygun birden fazla yol varsa ne olur?

str> foozboozer
pat> f.*z
foozboozer
~~~~~~~~

Düzenli ifadeler olabilecek en uzun dizgiyi döndürdüğü için fooz'un yerine foozbooz eşleştirildi.

Aşağıda iki nokta üstüste işaretiyle sınırlandırılmış bir zaman alanı bulunuyor:

str> Wed Feb  7 08:58:04 JST 1996
pat> [0-9]+:[0-9]+(:[0-9]+)?
Wed Feb  7 08:58:04 JST 1996
           ~~~~~~~~

"=~" operatörü bulduğu dizginin konumunu döndüren, aksi halde nil döndüren düzenli ifadedir.

ruby> "abcdef" =~ /d/
   3
ruby> "aaaaaa" =~ /d/
   nil


Dizgiler
Önceki
İçindekiler
İçindekiler
Diziler
Sonraki