11.Regular Expressions

Regular Expressions = Düzenli İfadeler

Düzenli ifadeler matematikten programlamaya aktarılmış bir kavramdır. Bir yazı içerisinde düzenli ifade formatına uygun olan alt yazıyı bulmaya yarar. Düzenli ifadeler kendi içerisinde bir takım özel karakterlere sahiptir. Bu karakterler ile bir düzenli ifade oluşturulur ve bu düzenli ifade içerisinde belirli koşula uygun olan yazı elde edilir. Düzenli ifade ayrıştıran programları yazmak zordur. Bu programlara genel RegEx Engine(Düzenli İfade Motorları) denilmektedir. Düzenli ifadeler için herhangi bir standart yoktur. Bir çok programlama ortamında desteklenir, belirli bir standart olmamasına karşın birbirlerine çok benzemektedir.

Java'da düzenli ifadeler için temel olarak 3 tane sınıf kullanılmaktadır:

  • matcher
  • pattern
  • pattern syntax exception

Bu sınıflar java.util.regex paketi içerisinde bulunmaktadır. Bu sınıfların başlangıç metotları yoktur.

/*----------------------------------------------------------------------------------------------------------------------
    Bir yazı içerisindeki sayıları düzenli ifade ile elde eden program
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {
        String regex = "[0-9]+";

        String text = "Bugün hava 30 derece, dün 25 dereceydi";

        Pattern pattern = Pattern.compile(regex);

        Matcher m = pattern.matcher(text);

        while (m.find()) {
            System.out.println(text.substring(m.start(), m.end()));
        }

    }
}
/*----------------------------------------------------------------------------------------------------------------------
    Yukarıdaki işlemin bir eşdeğeri
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {
        String regex = "[^a-zA-Züğçş, ]+";

        String text = "Bugün hava 30 derece, dün 125 dereceydi";

        Pattern pattern = Pattern.compile(regex);

        Matcher m = pattern.matcher(text);

        while (m.find()) {
            System.out.println(text.substring(m.start(), m.end()));
        }

    }
}
/*----------------------------------------------------------------------------------------------------------------------
    Tarihe ilişkin bir düzenli ifade
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {
        String regex = "\\d{1,}/\\d{1,}/\\d{2,}";

        String text = "Ben 10/9/1976 yılında doğdum. Kardeşim 12/12/77 yılında doğdu";

        Pattern pattern = Pattern.compile(regex);

        Matcher m = pattern.matcher(text);

        while (m.find()) {
            System.out.println(text.substring(m.start(), m.end()));
        }        
    }
}
/*----------------------------------------------------------------------------------------------------------------------
    Basit bir email adres düzenli ifadesi
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {
        String regex = "[a-z0-9]+@[a-z0-9]+\\.[a-z]+";

        String text = "Mail adresin [email protected], eski mail adresim [email protected] dur";

        Pattern pattern = Pattern.compile(regex);

        Matcher m = pattern.matcher(text);

        while (m.find()) {
            System.out.println(text.substring(m.start(), m.end()));
        }

    }
}

Düzenli ifadeler için özel bazı semboller bulunmaktadır. Düzenli ifadelere ilişkin bu sembollerin birleşimine kalıp(pattern) denilmektedir. Bu kalıplar çeşitli şekillerde oluşturulabilir.

Düzenli İfadelerde Kalıpların Oluşturulması

Düzenli ifadelerde kalıplar çeşitli şekillerde oluşturulabilir

Karakter Sınıfları (Character Classes)

Karakter sınıfları köşeli parantez içerisinde kalan karakterleri temsil etmektedir. Örnek karakter sınıfları şunlar olabilir;

Meta Karakterler

Düzenli ifadeler için aşağıdaki karakterlerin özel bir anlamı vardır, eğer bu karakterler özel anlamı dışında kullanılmak istiyorlarsa "^" işareti kullanılmalıdır.

<([{\^-=$!|]})?*+.>

Karakter Açıklama
. /n dışındaki herhangi bir karakter
* Solundaki karakterden 0 tane yada çok tane
+ Solundaki karakterden 1 tane yada çok tane
? Solundaki karakterden 0 tane yada 1 tane
{n} Solundaki karakterden tam olarak n tane
{n,} burada n bir sayıdır, solundaki karakterden en az n tane
Soru İşareti Solundaki karakterden 0 tane yada 1 tane
{n,m} solundaki karakterden en n tane, en fazla m tane
[ ] içerisindeki karakterlerden herhangi birisi
x-y x ve y aralığındaki herhangi bir karakter
köşeli parantez içerisindeki olmayan herhangi bir karakter
\w herhangi bir alfa numerik karakter
\W Alfa numerik olmayan karakter
\s herhangi bir boşluk karakteri(whitespace)
\S herhangi bir boşluk olmayan karakter
$ satırın sonunun belli karakterlerle sonlanması durumu
^ satır başı belli karakterlerle başlaması durumu
(...) gruplama amacında kullanılır böylece bunun sağındaki meta karakterler bir grup içib anlam kazanır
I veya anlamına gelmektedir
/d digitin kısaltılması, herhangi bir sayısal karakter
/D sayısal karakter olmayan

Sınıf Çalışması:

Adı soyadı ve email adresi bir form ile girilen bir uygulamasında ad soyad bilgisinin ve email adresi bilgisinin geçerliliğini Servlet tarafında kontrol eden ve duruma göre mesaj gönderen programı yazınız.

Örnek karakter sınıfları:

Karakter Açıklama
[0-9] 0 ile 9 arasındaki rakamlardan herhangi birisi varsa al
[a-zA-Z] Büyük veya küçük harf olan herhangi bir İngilizce alfabedeki karakter
[a-zA-ZçğıöşüÇĞIOÖŞÜ] Büyük veya küçük harf olan herhangi bir Türkçe alfabedeki karakter

Bir düzenli ifadede doğrudan bulunan bir karakter özel bir anlam ifade etmiyor ise kalıp içerisine doğrudan dahil edilmiştir. Örn: [a-zA-Z]@

Anahtar Notlar: Anımsanacağı gibi ingillizce alfabedeki 22 karakterin büyük ve küçük olanları standart UNICODE tablosunun ilk 128 karakterine belirli bir sıraya göre serpiştirilmiştir. Fakat Türkçe karakterler ilk 128 içerisinde değildir ve standart olarak kabul edilmez. Bu durumda programcı bir düzenli ifadede Türkçe karakterleri de bulmak istiyorsa karakter kümesine onları da eklemelidir.

Sınıf Çalışması

Klavyeden girilen bir yazı içerisinde mail adreslerine ilişkin "@" karakterinden öncesi ve domain ismini ayrı ayrı elde eden programı yazınız.

/*----------------------------------------------------------------------------------------------------------------------
    Bir yazı içerisinde mail adreslerine ilişkin @ karakteri öncesi ve 
    sonrasını elde eden program
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {
        String regex = "[a-zA-Z0-9.]+";
        String text = "[email protected]";

        Pattern pattern = Pattern.compile(regex);

        Matcher m = pattern.matcher(text);

        while (m.find()) {
            System.out.println(text.substring(m.start(), m.end()));
        }

    }
}

Sınıf Çalışması

Parametresiyle aldığı bir yazının Java'da geçerli bir değişken ismi olup olmadığını kontrol eden isIdentifier isimli metodu düzenli ifade kullanarak yazınız ve test ediniz.

/*----------------------------------------------------------------------------------------------------------------------
    Sınıf Çalışması: Parametresi ile aldığı bir yazının
    Java'da geçersi bir değişken ismi olup olmadığını kontrol eden 
    isVariable isimli metodu yazınız ve test ediniz
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.csystem.utils.Keyboard;

public class App {
    public static void main(String[] args) 
    {

        Keyboard kb = new Keyboard();

        String name;

        while (!(name = kb.getLine("İsim?")).equals("exit")) {        
            System.out.println(Utils.isVariable(name) ? "Geçerli" : "Geçersiz");
        }
    }
}

class Utils {
    public static boolean isVariable(String s)
    {
        String patternStr = "^[a-z_A-Z][a-zA-Z0-9]*$";

        Pattern pattern = Pattern.compile(patternStr);

        Matcher m = pattern.matcher(s);

        int count = 0;

        while (m.find()) {
            count++;
            if (count == 2)
                break;
        }

        return count == 1;
    }
}
/*----------------------------------------------------------------------------------------------------------------------
    Yukarıdaki sınıf çalışmasında değişken isimlerinde Türkçe karakterler de 
    kullanılabilen versiyon
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.csystem.utils.Keyboard;

public class App {
    public static void main(String[] args) 
    {

        Keyboard kb = new Keyboard();

        String name;

        while (!(name = kb.getLine("İsim?")).equals("exit")) {        
            System.out.println(Utils.isVariable(name) ? "Geçerli" : "Geçersiz");
        }
    }
}

class Utils {
    public static boolean isVariable(String s)
    {
        String patternStr = "^[a-z_A-ZçÇğĞıİöÖüÜ][a-zA-Z0-9çÇğĞıİöÖüÜ]*$";

        Pattern pattern = Pattern.compile(patternStr);

        Matcher m = pattern.matcher(s);

        int count = 0;

        while (m.find()) {
            count++;
            if (count == 2)
                break;
        }

        return count == 1;
    }
}

Examples.txt'den örnekler;

/*----------------------------------------------------------------------------------------------------------------------
    Sınıf Çalışması: String sınıfının split metoduna kolay bir kullanım örneği
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

public class App {
    public static void main(String[] args) 
    {        
        String str = "Bugün hava      :;?çok güzel";

        for (String s : Utils.split(str, " :\t;?", StringSplitOptions.REMOVEEMPTYENTRIES))
            System.out.println(s);

    }
}

enum StringSplitOptions {NONE, REMOVEEMPTYENTRIES}

class Utils {
    public static String [] split(String s, String delims, StringSplitOptions op)    
    {
        if (s == null || delims == null || delims.isEmpty() || op == null)
            throw new IllegalArgumentException("Invalid arguments");

        String regex = "[" + delims + "]";

        if (op == StringSplitOptions.REMOVEEMPTYENTRIES)
            regex += "+";

        return s.split(regex);        
    }
}
/*----------------------------------------------------------------------------------------------------------------------
    Karakter sabitlerinin \u ile yazılmasının regex için kullanımı
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {        
        String str = "1Ö223Ö";

        String pattern = "^[a-z" + '\u00D6' + "0-9]+$";

        Pattern p = Pattern.compile(pattern);

        Matcher m = p.matcher(str);

        while (m.find())
            System.out.println(str.substring(m.start(), m.end()));                
    }
}


/*----------------------------------------------------------------------------------------------------------------------
    Karakter sabitlerinin \u ile yazılmasının regex için kullanımı
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {        
        String str = "1Ö223Ö";

        String pattern = "^[a-z\u00D60-9]+$";

        Pattern p = Pattern.compile(pattern);

        Matcher m = p.matcher(str);

        while (m.find())
            System.out.println(str.substring(m.start(), m.end()));                
    }
}


/*----------------------------------------------------------------------------------------------------------------------
    Düzenli ifadeler
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {        
        String str = "ch:(12):ch:(23) ali ch:(34) ";

        String pattern = "ch:\\([0-9]+\\)";

        Pattern p = Pattern.compile(pattern);

        Matcher m = p.matcher(str);

        while (m.find())
            System.out.println(str.substring(m.start(), m.end()));                
    }
}

/*----------------------------------------------------------------------------------------------------------------------
    Düzenli ifadeler
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class App {
    public static void main(String[] args) 
    {        
        String str = "Bugün" + (char)13 + "hava\r" + (char)13 + "çok\r";
        String [] words = str.split(String.format("[%c]+", (char)(13)));

        for (String s : words)
            System.out.println(s);

    }
}

Gruplama işlemi parantezlerle yapılmakatadır ;

örneğin; ([a-z]3) bu kalıpta a ile z arasındaki karakterlerden, karakterinden 3 tane olabilir. xy_z gibi bir yazı geçerli olacaktır.

Sınıf çalışması

String sınıfınnın Split methodu RegEx kullanmadan ayraçları, bir String içierisine alacak bir method tasarlayınnız ve yazınız.

/*----------------------------------------------------------------------------------------------------------------------
    Sınıf Çalışması: String sınıfının split metoduna kolay bir kullanım örneği
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

public class App {
    public static void main(String[] args) 
    {        
        String str = "Bugün hava      :;?çok güzel";

        for (String s : Utils.split(str, " :\t;?", StringSplitOptions.REMOVEEMPTYENTRIES))
            System.out.println(s);

    }
}

enum StringSplitOptions {NONE, REMOVEEMPTYENTRIES}

class Utils {
    public static String [] split(String s, String delims, StringSplitOptions op)    
    {
        if (s == null || delims == null || delims.isEmpty() || op == null)
            throw new IllegalArgumentException("Invalid arguments");

        String regex = "[" + delims + "]";

        if (op == StringSplitOptions.REMOVEEMPTYENTRIES)
            regex += "+";

        return s.split(regex);        
    }
}

Sınıf Çalışması :

Bir text dosya içerisinde satır satır kişi bilgileri bulunsun, kişilerin bilgileri şu formatta (Oğuz Karan Bahçeşehir 10/09/1976 Zonguldak ) fakat karışık şekilde olacaktır. Buna göre bu text dosyada bulunan kişilern yaşları ortalamasını bulan programı yazınız.

/*----------------------------------------------------------------------------------------------------------------------
    Sınıf Çalışması: Bir text dosya içerisinde satır satır aşağıdaki gibi satırlarsdan
    oluşsun

    Oguz Karan Bahcesehir 10/09/1976 zonguldak

    Burada ki bilgiler karışık sırada bulunabilir. Buna göre text dosya içerisindeki 
    bulunan kişilerin yaşları ortalamasını bulunuz.
    Dosya bilgileri:

    oguz karan bahcesehir 10/09/1976 zonguldak
    zekiye cakiral 05/01/1991 trabzon uskudar
    yusuf bicakcioglu kastamonu 15/10/1974 atasehir
    oguzhan goller bakirkoy ardahan 10/01/1994
    30/05/1983 gurur oner kirsehir bahcelievler
    istanbul fatih serhat erbas 27/10/1988
    ozgur sezgin kirklareli beyoglu 11/08/1982
    mert demir bursa 06/09/1994 sisli
    selman sahin giresun eyup  22/03/1984
    ilker toksoz nevsehir bahcelievler 16/12/1986 
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

import org.csystem.utils.Util;

public class App {
    public static void main(String[] args) 
    {            
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("people.txt")))) {
            String patternDate = "\\d{1,2}/\\d{1,2}/\\d{4}";
            String patternDateParse = "[0-9]+";
            String line;

            LocalDate now = LocalDate.now();

            double sum = 0;
            int numberOfPeople = 0;

            while ((line = br.readLine()) != null) {
                ++numberOfPeople;
                String birthDateStr = Util.matchRegex(patternDate, line)[0];
                String [] bdate = Util.matchRegex(patternDateParse, birthDateStr);

                LocalDate birthDate = LocalDate.of(Integer.parseInt(bdate[2]), Integer.parseInt(bdate[1]), Integer.parseInt(bdate[0]));
                sum += ChronoUnit.DAYS.between(birthDate, now) / 365.;            
            }

            System.out.printf("Yaş ortalaması=%.2f%n", sum / numberOfPeople);        

        }
        catch (Throwable ex) {
            System.out.printf("%s:%s", ex.getClass().getName(), ex.getMessage());
        }
    }
}

Sınıf Çalışması:

Yukarıdaki sınıf çalışmasında kişilerin işe giriş tarihleri de herhangi bir yerde bulunsun(Satır içerisinde ) buna göre yaş ortalamasını bulan programı tekrar düzenleyiniz.

/*----------------------------------------------------------------------------------------------------------------------
    Sınıf Çalışması: Yukarıdaki sınıf çalışmasında kişilerin işe giriş tarihleri de
    rherhangi bir yerde (satır içerisinde) bulunsun buna göre yaş ortalamasını bulan
    programı tekrar düzenleyiniz:
    Dosya Bİlgileri:

    oguz karan bahcesehir 01/10/2012 10/09/1976 zonguldak
    zekiye cakiral 05/01/1991 trabzon 06/04/2015 uskudar
    yusuf bicakcioglu kastamonu 15/10/1974 05/4/2016 atasehir
    oguzhan goller bakirkoy ardahan 10/01/1994 07/10/2015
    30/05/1983 gurur 15/7/2016 oner kirsehir bahcelievler
    istanbul 10/08/2014 fatih serhat erbas 27/10/1988
    ozgur sezgin 16/04/2014 kirklareli beyoglu 11/08/1982
    mert demir bursa 01/01/2017 06/09/1994 sisli
    selman sahin 05/11/2013 giresun eyup 22/03/1984
    ilker toksoz nevsehir bahcelievler 16/12/1986 06/03/2016
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

import org.csystem.utils.Util;

public class App {
    public static LocalDate makeLocalDate(String [] birthDate)
    {
        return LocalDate.of(Integer.parseInt(birthDate[2]), Integer.parseInt(birthDate[1]), Integer.parseInt(birthDate[0]));        
    }

    public static LocalDate minDate(LocalDate [] dates)
    {
        LocalDate result = dates[0];

        for (int i = 1; i < dates.length; ++i) 
            if (result.isAfter(dates[i]))
                result = dates[i];        

        return result;

    }

    public static void main(String[] args) 
    {            
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("people.txt")))) {
            String patternDate = "\\d{1,2}/\\d{1,2}/\\d{4}";
            String patternDateParse = "[0-9]+";
            String line;

            LocalDate now = LocalDate.now();

            double sum = 0;
            int numberOfPeople = 0;

            while ((line = br.readLine()) != null) {
                ++numberOfPeople;

                String [] birthDateStr = Util.matchRegex(patternDate, line);

                LocalDate [] dates = new LocalDate[birthDateStr.length];

                int index = 0;
                for (String s : birthDateStr) {
                    String [] bdate = Util.matchRegex(patternDateParse, s);
                    dates[index++] = makeLocalDate(bdate);
                }

                LocalDate birthDate = minDate(dates);

                sum += ChronoUnit.DAYS.between(birthDate, now) / 365.;            
            }

            System.out.printf("Yaş ortalaması=%.2f%n", sum / numberOfPeople);        

        }
        catch (Throwable ex) {
            System.out.printf("%s:%s", ex.getClass().getName(), ex.getMessage());
        }
    }
}

results matching ""

    No results matching ""