İngilizce Kaynaklar


Diğer




Düzenli İfadeler [Regular Expressions]

Çeviren: Ali Çehreli
Tarih: 14 Temmuz 2009

Düzenli ifadeler, metinlerin belirli bir desene uyanlarını bulmaya ve eşleştirmeye yarayan çok güçlü araçlardır. Düzenli ifadeler Perl, Ruby, Javascript gibi dillerin iç olanaklarıdırlar ve özellikle Perl ve Ruby'de son derece beceriklidirler. Peki düzenli ifadeler D'de neden dilin iç olanakları arasında değildir? Aşağıda düzenli ifadelerin D'de Ruby'den ne farklılıklar gösterdiğini bulacaksınız.

Bu makale düzenli ifadelerin D'de nasıl kullanıldıklarını gösterir ama düzenli ifadelerin ne olduklarını anlatmaz. Ne de olsa salt düzenli ifadeleri kapsayan kitaplar yazılmıştır. D'nin düzenli ifadeler olanağı bütünüyle Phobos kütüphanesinin std.regex modülünde tanımlanmıştır. Düzenli ifadelerin şablonlarla bağıntılı olarak ileri düzey kullanımlarını görmek için Templates Revisited yazısını da okuyabilirsiniz.

Düzenli ifadeler Ruby'de özel dizgi sabitleri olarak oluşturulurlar:

r = /desen/
s = /p[1-5]\s*/

D'de özel sabitler olarak değil, nesne olarak oluşturulurlar:

r = RegExp("desen");
s = RegExp(r"p[1-5]\s*");

Desen içindeki \ karakterlerinin C'de olduğu gibi çift olarak yazılmaları gerekmez; başlarındaki r karakteriyle belirtilen wysiwyg dizgiler ("sonuç gördüğünle aynıdır" anlamında) kullanılabilir. Bu kodda r ve s nesnelerinin türü RegExp'tir ama türleri otomatik olarak da belirlenebilir:

auto r = RegExp("desen");
auto s = RegExp(r"p[1-5]\s*");

Bir düzenli ifadenin bir s dizgisine uygunluğunu Ruby'de bulmak için =~ işleci kullanılır. Bu işleç, aranan desenin dizgi içinde uyduğu ilk yerin indeksini döndürür:

s = "abcabcabab"
s =~ /b/   /* uyar, 1 döndürür */
s =~ /f/   /* uymaz, nil döndürür */

Bunun D'deki eşdeğeri şöyledir:

auto s = "abcabcabab";
std.regexp.find(s, "b");    /* uyar, 1 döndürür */
std.regexp.find(s, "f");    /* uymaz, -1 döndürür */

Bunun std.string.find'a benzerliğine dikkat edin: std.string.find'ın farkı, düzenli ifadeye uyan kısmı değil, bir alt dizgiyi bulmasıdır.

Ruby'nin =~ işleci, aramanın sonuçlarını gösteren bazı özel değişkenleri otomatik olarak tanımlar:

s = "abcdef"
if s =~ /c/
    "#{$`}[#{$&}]#{$'}"   /* "ab[c]def" dizgisinin esdegeridir

std.regexp.search() ise uyanların bilgisini taşıyan bir RegExp nesnesi döndürür:

auto m = std.regexp.search("abcdef", "c");
if (m)
    writefln("%s[%s]%s", m.pre, m.match(0), m.post);

veya daha kısaca:

if (auto m = std.regexp.search("abcdef", "c"))
    writefln("%s[%s]%s", m.pre, m.match(0), m.post);
                                           // "ab[c]def" yazar
Metin Arama ve Değiştirme

Bu işlem biraz daha ilginçtir. "a"ların önce ilkini, sonra da hepsini "ZZ" ile değiştirmenin yolu Ruby'de şudur:

s = "Tavuğa roket tak."
s.sub(/a/, "ZZ")            // sonuç: "TZZvuğa roket tak."
s.gsub(/a/, "ZZ")           // sonuç: "TZZvuğZZ roket tZZk."

D'de ise şöyle:

s = "Tavuğa roket tak.";
sub(s, "a", "ZZ");          // sonuç: "TZZvuğa roket tak."
sub(s, "a", "ZZ", "g");     // sonuç: "TZZvuğZZ roket tZZk."

Eskisinin yerine gelecek olan metin parçasının içinde, uyan metin parçalarını belirten $&, $$, $', $`, .. 9 belirteçleri kullanılabilir:

sub(s, "[at]", "[$&]", "g");
                        // sonuç: "T[a]vuğ[a] roke[t] [t][a]k."

veya yerleştirilecek dizgi bir delegate tarafından verilebilir:

sub(s, "[at]",
   (RegExp m) { return toupper(m.match(0)); },
   "g");                // sonuç: "TAvuğA rokeT TAk."

(toupper() std.string modülünde tanımlanmıştır.)

Döngüler

Bir dizgi içindeki uyan bütün yerler bir döngüyle şöyle görülebilir:

import std.stdio;
import std.regexp;

void main()
{
    foreach(m; RegExp("ab").search("abcabcabab"))
    {
        writefln("%s[%s]%s", m.pre, m.match(0), m.post);
    }
}
// Çıktısı:
// [ab]cabcabab
// abc[ab]cabab
// abcabc[ab]ab
// abcabcab[ab]
Sonuç

Düzenli ifadeler D'de de Ruby kadar güçlüdürler ama yazımları onunki kadar kısa değildir:

Yine de aynı derecede güçlüdür.