Post Page Advertisement [Top]

Merhaba,
Bu yazımda C# da harika bir regex örneği oluşturacağız , büyük bir heyecan içinde hemen senaryodan bahsedeyim :) Bir SMS sisteminizin olduğunu düşünün, insanlar size AD SOYAD ŞEHİR YAŞ ve NUMARA ' larını SMS olarak atacaklar siz bu yazıdan kullanıcının telefon numarasını ,numerik olmayan yazı içeren kısmı (yani AD SOYAD  ŞEHİR) bulacaksınız ve de yaşını.Ayrıca yanlış sırada SMS atan (ör: AD SOYAD ŞEHİR NUMARA YAŞ) kullanıcı SMS 'ini de düzgün sıraya çevireceğiz.(NUMARA ve YAŞ alanları yer değiştirecek.)



Bunun için önce boş bir websitesi oluşturalım Defaul.aspx adında bir sayfası olsun,ve bahsettiğimiz senaryo için bir TextBox ,bir Button ve bir Label oluşturalım.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Regex Sample</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:TextBox Height="40" Width="600px" runat="server" ID="message_box"></asp:TextBox>
            <asp:Button runat="server" ID="create_btn" Text="Create" OnClick="create_btn_Click" />
            <asp:Label runat="server" ID="alert_lbl" />

        </div>
    </form>
</body>

</html>

Button click eventte ProduceCorrectMessage adında doğru mesajı üreten bir metodu çağıralım ve tabii ki bu metodun içini belirttiğimiz senaryo için kodlayalım.

    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void create_btn_Click(object sender, EventArgs e)
    {
        alert_lbl.Text = ProduceCorrectMessage(message_box.Text);
    }

    private string ProduceCorrectMessage(string messageBodyText)
    {
        string correct_message = "";

        try
        {

        }
        catch
        {
           
        }

        return correct_message;
    }


İlk olarak mesajdan kullanıcı numarasını Regex ile bulmaya çalışalım. Ben bu satırdan sonra kullanıcı numarası yerine "Msisdn" terimini kullanacağım , bir telekominikasyon terimi :) 
Öncelikle şunu da belirteyim ki aynı işi Regex ile farklı şekillede yapmak mümkün ben aşağıdaki şekilde bir yol izleyeceğim.İlk olarak mesajdaki tüm boşlukları yok edeceğim ve daha sonra Türkiye için mobil operatörlerin 5XX XXX XX XX formatında numara üretiğini düşünerek bu formattaki numerik alanı yakalamaya çalışacağım.Aşağıdaki iki satır bunu anlatmakta.

try
        {
            string txt = messageBodyText.Replace(" ", "");
            string user_msisdn = Regex.Match(txt, @"5[0-9]{2}[0-9]{7}").Value;

Regex ifadeyi sizler için detaylandırayım. Öncelikle 5 ,"5" rakamı ile başlaması gerekiğini söylüyor. regex'in önünde ^ olmadığı için önünde başka karakterlerde olabilir demek başka rakam yazı gibi... ardından gelen[0-9] 0 ile 9 rakam kümesinden elemanlar olabilir demek peki kaç defa olabilir 2 defa yani beşten sonra iki hane geriye kaldığından {2} rakamı da bunu ifade etmekte.benzer şekilde [0-9]{7} şunu ifade etmekte geri kalan 7 haneli olmalı ver 0-9 rakam kümesinden herhani bir eleman olabilir demek sonunda $ işareti olmadığında bu pattern'den sonra rakam yazı vb. karakterler gelebilir anlamındadır.

Bu arada yazdığınız regex ifadelerini test edebileceğiniz harika bir yer var: regex101 ben tüm testlerimi burada test ediyorum. Test için aşagıdaki mesajı kullandım. Bilerek yaş kısmını yanlış yazıp sona yazdım.Soyad ve Şehir arasında da  fazla boşluk bıraktım.

"SEMA KUDU   İSTANBUL  905546785609 20"


Bu aşamadan sonra mesajdan msisdn alanını çıkarıp ad soyad şehir kısmını bulalım ve fazla konulan boşluk olsa bile formatlayıp teke indirelim.

            string step1 = messageBodyText.Replace(user_msisdn, "");
            string user_text = Regex.Match(messageBodyText, @"[A-z^şŞıİçÇöÖüÜĞğ\s]*").Value;


Hemen yeni regex'i anlatmaya çalışayım burda görüldüğü gibi A-z arasında yani küçük ve büyğh harfler dahil tüm alfabetik karakterleri bulabilir demektir. A-z den sonra gelen Türkçe alfabeye özgü olan harfler ise Türk.e karakterleri yakalayabilmek için eğer boyle yapmazsanız Regex defaultta İngilizce alabeyi baz alıyor ve türkçe karakter gördüğü anda ifadeyi match etmeyi kesiyor.Yani kısacası türkçe desteklemiyor :)  Türkçe harfleri(büyük ve küçük dahil desteklemesi için ) ^şŞıİçÇöÖüÜĞğ  ifadesini yazdık.  gelelim sonda yer alan \s ifadesine bu da harfler arasında yani kelimeler arasında boşluk tab gibi whitespace karakerler olabilir demektir.[A-.....]* "*" ise bu kümenin ya hiç gelmeyeceğini ya da bir çok defa tekrarlayabileceğini ifade ediyor.



Gelelim yaş bulma adımına bu kısım diğerlerini  göre biraz daha karışık çünkü 5XX XXX XX XX numara alanını ve yazı alanını çıkardığımızda numarasını 05XX... ya da 905XXX... şeklinde yazan kullanıcılar için geriye  90 20 ya da 0 20 ya da +90 20  yazısı kalıyor eğer kullanıcı numarasını doğru formatta yazmış ise zaten geriye sadece 20 kalıyor ama bu iyi senaryo :) Şimdi yaş çıkarımı yapalım .Bu arada kullanıcı yaşını numaradan önce yazar ise 20 0 , 20 90 ya da 20 +90 ifadeleri geriye kalabilir. Bu geriye kalan text üzerine yapacağımız işlemler için ExtractAge adına bir metod yazdım.

string step2 = step1.Replace(user_text, "");

string user_age = ExtractAge(step2);

private string ExtractAge(string user_age)
    {
        string CorrectAge = "";

        try
        {
            user_age = user_age.Replace(" ", "");
            CorrectAge = user_age.Substring(0, 2);

            if (user_age.StartsWith("+") || user_age.StartsWith("0") || user_age.StartsWith("9"))
                CorrectAge = user_age.Substring(user_age.Length - 2, 2);
        }
        catch
        {
            //Log.Error(ex1.Message, ex1);
        }

        return CorrectAge;
    }


Geriye  kalan text'deki tüm boşlukları ilk satırdaki kod ile siliyoruz.Sonra String.Substring ile ilk iki karakterini alıyoruz. Bu durum yaşını numarasından önce yazmış kullanıcılar için doğru oluyor sonraki if şartında bu durumun tersi ise yani yaşını  msisdn'den sonra yazmış ise durumunu kontrol ediyor o zamanda sonra iki rakamı alıyoruz. İki hane almamızın sebebi kullanıcıların yaşının 2 haneli olmasını bekliyoruz :)

Aslında işlemin büyük bir kısmını halettik son olarak iki işlem yapıp doğru mesajı üreteceğiz.İlk olarak msisdn'ları ormatlayalım yani 5XXXXXXXXX şeklinde olan numarayı okunabilirlik açısında  05XX XXX XX XX şekline getirelim.


string formatted_msisdn = FormatMsisdn(user_msisdn);


private string FormatMsisdn(string msisdn)
    {
        string FormattedMsisdn = "";

        try
        {
            string m1 = msisdn.Substring(0, 3);
            string m2 = msisdn.Substring(3, 3);
            string m3 = msisdn.Substring(6, 2);
            string m4 = msisdn.Substring(8, 2);

            FormattedMsisdn = "0" + m1 + " " + m2 + " " + m3 + " " + m4;

        }
        catch
        {
            //Log.Error(ex1.Message, ex1);
        }

        return FormattedMsisdn;
    }

İkinci olarak yazı alanındaki(ad soyad şehir) gereksiz boşlukları teke indirelim.Yine bunun içinde bir regex kullanacağız daha önce whitespace karakterlerini temsil eden \s den faydalanacağız.

string formatted_user_text = DeleteRepeatedSpaces(user_text);

private string DeleteRepeatedSpaces(string text)
    {
        string FormattedText = "";
        try
        {
            FormattedText = Regex.Replace(text, @"\s+", " ");
        }
        catch
        {

        }
        return FormattedText;
    }

Şimdi düzgün mesajı elde edebiliriz.SMS'i doğru atanlanlar için bir sorun olmayacaktır :)

correct_message = formatted_user_text + user_age + " " + formatted_msisdn;


 ProduceCorrectMessage metodunun son hali aşagıdaki gibi olacaktır.


    private string ProduceCorrectMessage(string messageBodyText)
    {
        string correct_message = "";

        try
        {
            string txt = messageBodyText.Replace(" ", "");
            string user_msisdn = Regex.Match(txt, @"5[0-9]{2}[0-9]{7}").Value;

            string step1 = messageBodyText.Replace(user_msisdn, "");
            string user_text = Regex.Match(messageBodyText, @"[A-z^şŞıİçÇöÖüÜĞğ\s]*").Value;

            string step2 = step1.Replace(user_text, "");
            string user_age = ExtractAge(step2);
           
            string formatted_msisdn = FormatMsisdn(user_msisdn);
            string formatted_user_text = DeleteRepeatedSpaces(user_text);
            correct_message = formatted_user_text + user_age + " " + formatted_msisdn;

        }
        catch
        {
            //Log.Error( ex1.Message, ex1);
        }

        return correct_message;
    }

Şimdi projemizi test edebiliriz aşağıda bir kaç test görüntüsü var.

SEMA KUDU   İSTANBUL  905546785609 20

SEMA KUDU   İSTANBUL 20  +905546785609 
Evet sevgili takipçilerim yaş ve telefon numarası doğru olmamakla  birlikte :D bu yazımızın da sonuna geldik. Tam projeyi burada bulabilirsiniz.
Teşekkürler, sağlıkla , mutlulukla kalın.
Ne dinlemeli alanını unutmadım tabi :)

4 yorum:

  1. Bu akşam o kadar çok sevaba girdinizki anlatamam. 2 gündür regex için japon alfabesi için regex arıyordum.verdiğiniz sitede buldum teşekkurler..

    YanıtlaSil
  2. Faydalı olabildiysem ne mutlu, okuduğunuz için teşekkürler.

    YanıtlaSil
  3. Kodda arızalı kısımlar var Substring yapmak ileride sıkıntıya sokabilir. Regex'iniz iyi çalışmıyor.

    YanıtlaSil
    Yanıtlar
    1. Merhaba, ilginiz için teşekkürler,iyi çalışmıyor dediğiniz kısım neresidir acaba? Teşekkürler.

      Sil

Bottom Ad [Post Page]