Kurallı İfadeler (regex Engine)

Bir regex'in gerçekte nasıl çalıştığını bilmek daha efektif çalışan regex ifadeleri oluşturmamızı ve regex'leri daha isabetli oluşturmamızı sağlar. Bu yazımızda oluşturduğunuz regex ifadelerinin neden beklediğiniz sonuçları vermediğini ve umduğunuz eşleşmeleri yerine getirmediğini öğreneceksiniz. Bu da bizim tabir yerindeyse daha az kafa patlatmamızı ve daha az zaman harcamamızı sağlayacaktır.
www.dijitalders.com

Regex Engine Çeşitleri

Regex engine'lar iki farklı şekilde çalışırlar.

        * text-directed (metin bazlı)
        * regex-directed (regex bazlı)

Popüler olanı 2.si yani Regex-directed engine'lardır. Çünkü referanslar ve tembel davranış biçimi gibi bir takım kullanışlı özellikleri vardır. Text-directed çalışan çok az engine vardır. Bunlardan biri mySQL dir, belki de en hatırı sayılır örnek olarak..
Regex-directed Soldakini Tercih Eder

Regex-directed engine'ların en ayırtedici özelliği solu tercih etmesidir. Örneğin evim ifadesi evim|evim. ifadesindeki kelimelerden ikisi ile de eşleşecektir ama en baştaki evim kelimesine öncelik verecektir. Text-directed engine ise sağdakini önce iletecektir.

Bir regex ilk olarak metin içerisindeki ilk karakteri deneyecektir. Tüm permütasyonları denedikten sonra, ilk karakterle eşleşemezse ikinci karakteri deneyecektir ve böyle sonraki karakterlerle devam edecektir.

Örneğin kara ifadesi ile bugün kar ankara'ya yağmadı. cümlesini düşünelim. İlk olarak kara kelimesinin ilk harfi k, cümlenin ilk harfi b ile eşleşmeye çalışacaktır. Eşleşmediği için regex devam edecektir. Taki k ile kar kelimesindeki ilk k eşleşene kadar.. Regex k'yı bulduktan sonra, burada duraklayıp kara kelimesinin diğer harflerini de eşleştirmeye çalışacaktır. k, a, r ile eşleştikten sonra a ile eşleşemeyince devam edecektir ve tekrar k harfini aramaya devam edecektir. Taki ankara kelimesindeki k harfini yakalayıncaya kadar. Daha sonra kara kelimesindeki diğer harfleri de eşleştirecek ve orada bekleyecektir. Çünkü regex bir sonuç bulduğunda onu hemen iletmek ister.

Bu örnek basit bir string işlemi gibi olsa da başlangıç için bilmek gereklidir. Daha sonraki örneklerimizde karışık ifadeleri ve nasıl çalıştıklarını inceleyeceğiz.

Regex Karakter Kümeleri

Karakter kümeleri ile metnin regex ifadesindeki herhangi bir karakterle eşleşmesini sağlayabiliriz. Bunun için eşleşecek karakterleri köşeli parantezler içine koyarız. Örneğin [vw] regex'i metin içindeki v veya w karakterleri ile eşleşecektir.

Köşeli parantez içindeki karakterlerin sırası önemli değildir.

Burada bir ayrıntıyı hatırlatmak gerekir. vw ifadelerini aramak isteseydik regex köşeli parantez kullanmadan yani vw şeklinde olacaktı. Örneğin metin içinde volkswagen ve wolkswagen kelimelerinin hepsini bulmak için kullanacağımız regex [vw]olkswagen olacaktır. Kullancının kelimenin ilk harfini doğru veya yanlış yazması farketmeyecektir. Burada yine dikkat! Regex vwolkswagen yada wvolkswagen ifadeleri ile eşleşmeyecektir. İlk karakter v yada w olabilir.

Karakter kümesi olarak aralık vermek için tire - kullanılır. [0-9] ifadesi 0 ile 9 arasındaki herhangi bir karakter ile eşleşir. Birden fazla aralıkta verebiliriz. Örneğin [0-9a-fA-F] büyük-küçük harf gözetmeden tek bir hexadecimal karakter ie eşleşir. Aralık ile beraber herhangi bir karakter de belirtilebilir. [0-9a-fxA-FX] tek bir hexadecimal karakter yada X karakteri ile eşleşir.

Negatif Karakter Kümeleri

Açılan köşeli parantezden sonra şapka ^ karakteri kullanmak karakter kümesi içindeki karakterlerle eşleşmeyen sonuçları bulacaktır. n[^s] iki karakter arayacaktır : n, ve s olmayan ikinci bir karakter. n[^s] regex ifadesi insanların kelimesindeki ns ile değil nl ile eşleşecektir. En sondaki n ile eşleşmeyecektir çünkü en sondaki n den sonra ikinci bir karakter bulunmamaktadır.

Özel Karakterler ve Karakter Kümeleri

Karakter kümeleri içindeki özel karakterler (yada metakarakterler) kapanan köşeli parantez ], ters bölü , şapka ^ ve tire - karakterleridir. Diğer özel karakterler köşeli parantez içerisinde normal karakterler gibi eşleşir ve öncesinde ters bölü kullanmaya gerek yoktur. Örneğin * veya + için [+*] ifadesi kullanılır.

Özel karakterleri karakter kümeleri içinde kullanırken öncesinde ters bölü kullanmak veya bu karakterleri özel bir anlam taşımayacağı yerde kullanmak gerekir. Örneğin [x^] ile [x^] gerçekte aynı ifadedir. Çünkü şapka ^ sadece açılan parantezden sonra özel bir karakterdir.

Unicode karakterler karakter kümeleri içinde normal kullanıldıkları gibi kullanılır. Örneğin [$u20AC], dolar $ veya euro € karakteri ile eşleşecektir. (euro karakterinin unicode karşılığı u20AC 'dir)

Regular Expressions

Regular expressions bir programlama dilinden ziyade programlama dillerinde kullanılan bir araçtır. Bu nedenle her programcının öğrenmesi gerekebilir. Biraz karışık gelebilir başlangıçta çünkü programcıların alışageldiği syntax'ten farklıdır.

Neden Regex (Regular Expressions)


Regex en çok metin ayrıştırma (string parsing) işlemlerinde kullanılır. Metin ayrıştırma işlemlerinde en çok kullanılan yöntemdir denebilir. Sebepleri ise

        * Çok fonksiyoneldir. En zor işlemler dahi çok kolay yapılır.
        * Genel bir araçtır. Her dilde, her platformda kullanılabilir.
        * Performanslı çalışır.

Bir kaç Regex örneği

Şu ifadeyle <A[^>]*>(.*?)</A> bir html sayfasındaki bağlantıları tarayabiliriz. Devamında yazabileceğimiz örneklerle yine html sayfasındaki bağlantıların tam yolunu bulabiliriz. Çünkü bu ifade sadece <a></a> taglarını bulmamızı sağlar. Tam yolu bulmak için

    href="http://www.noktalivirgul.com"

gibi tag attribute ları ayrıştırmak gerekir.

Regex'e Başlarken


Regex öğrenmek biraz pratik gerektirir. Aşağıdaki makaleler ile regex öğrenmeye başlangıç yapabilirsiniz. Ve hazırladığımız küçük bir web tabanlı uygulama ile basit regex ifadelerinizi oluşturabilir ve test edebilirsiniz.

    Regex ve Literaller

    Regex ve Özel Karakterler

    Regex ve Non-Printable Karakterler

    Regex Engine Nasıl Çalışır?

    Regex Karakter Kümeleri

Regular Expressions : Literal'ler

Regex kullanırken bilmemiz gereken en temel şeylerden biri hangi karakteri/kelimeyi nasıl arayacağımızdır. Aslında bu Regex öğrenmek için bir başlangıç noktası. Aşağıdaki basit örnekleri deneyerek ilk regex ifadelerinizi oluşturabilirsiniz.

Literaller


Basit bir regex ifadesi tek bir harften oluşur diyebiliriz. Örneğin tek bir a karakteri. Tek bir a karakterinden oluşan regex ifadesine ankara kelimesini argüman olarak verdiğimizde regex engine ankara kelimesindeki ilk a ile eşleşecektir.

ankara kelimesindeki diğer a karakterlerini de elde etmek için regex engine'a sonraki karakterleri de bulmasını ifade etmemiz gerekiyor. Bunu text editörlerinde Sonrakini Bul (Find Next) fonksiyonunu kullanarak yaparız genelde.

Tek bir karakterden ziyade bir kelime için de benzer şekilde basit regex ifadeleri oluşturulabilir. Örneğin pek regex ifadesi Türkiyenin sahilleri pek güzeldir. cümlesindeki pek ifadeleri ile eşleşir. Bununla regex engine'a sırayı gözeterekten önce p sonra e ve sonra k karakterleriyle eşleşen ifadeleri bulmasını söyleriz.

Burada şunu belirtmekte fayda var. Regex Engine'lar Büyük küçük harf duyarlıdır. Büyük küçük harf dikkate almadan çalışması için bunu belirtmemiz gerekiyor.

Regex İfadesinin pek ifadesi değil de pek kelimeleriyle eşleşmesini de sağlayabilirdik. Bu konuyu sonraki başlıklar altında ele alacağız.

Regular Expressions : Non-Printable Karakterler

Regex ifadelerinde görünmeyen karakterleri eşleştirmek için bu karakterler için tanımlanan özel ifadeleri kullanmalıyız. Örneğin regex ifadelerinde tab bulunamaz ve dolayısıyla tab karakterini eşleştirmek için t kullanılmalıdır.

CR (Carriage Return) için r, LF (Line Feed) için n, Boşluk karakteri için s kullanılır. Şunu hatırlatmakta fayda var; Windows tabanlı editörlerde satır sonu için rn, Unix tabanlılarda ise n ifadesi kullanılır.

Unicode Karakter Kodlarının Kullanımı


Ayrıca herhangi bir karakterin unicode code karşılığını kullanarak uFFFF şeklinde bu karakteri eşleştirebiliriz. Örneğin a karakterinin unicode karşılığı 0x0061'dir ve bu karakteri eşleştirmek için u0061 ifadesi kullanılır.

Regular Expressions : Özel Karakterler

Regex ifadeleri sadece basit literal'leri aramak için kullanılmamaktadır. Zaten basit aramalar yapmak için ilgili programlama dilinde kullanabileceğimiz metodlar mutlaka vardır. Gelişmiş regex ifadeleri oluşturmak için ihtiyaç duyduğumuz özel karakterler vardır.

Bu karakterler;

    Açılan köşeli parantez : [

    Ters bölü :

    Caret : ^

    Dolar işareti : $

    Nokta ., Soru işareti ?, Yıldız * ve Artı +

    Pipe : |

    Açılan parantez (, ve kapanan parantez )

Bu karakterleri bir metinde bulmak istersek öncesinde karakteri kullanmamız gerekir. Örneğin 1+ ifadesini literal olarak yani yazıldığı gibi aramak istersek 1+ regex ifadesi kullanmalıyız. regex olarak 1+ kullanılırsa + karakteri özel bir anlam kazanacaktır ve farklı ifadellerle eşleşecektir.

Özel karakterler yanlış kullanılırsa hata mesajı alınır. Örneğin +1 regex ifadesi hataladır ve exception döner.

Ters bölü işareti özel karakterlerle kullanıldığında onların literal olarak eşleşmesini sağlarken diğer karakterlerden önce kullanıldığında onlara farklı bir anlam verir. karakteri bunun için sihirli bir karakterdir ve kullanım alanlarını iyi bilmek gerekir.
Özel Karakterler ve Programlama Dilleri

Belki birşey dikkatinizi çekmiştir. Çoğu programlama dilinde özel karakter olarak kullanılan tek tırnak ve çift tırnak karakterleri Regular Expressions'da özel karakter değillerdir. Buna dikkat etmek gerekir. Özellikle regex tabanlı arama yapan text editörlerinde tek tırnağı ararken sadece bir tek tırnak kullanmak gerekir.

Ayrıca ters bölü işaretini kullanırken dikkat etmek gerekir. Örneğin c:windows ifadesini eşleştirmek için kullanacağımız regex ifadesi c:windows olmalıdır. Bunu bir programlama dilinde tanımlarken ise (örneğin C Sharp'ta) küçük bir değişiklik yapmak gerekir. Çünkü C Sharp'ta da string ifadelerinde ters bölü işareti özel bir karakterdir ve ters bölü işaretini string tanımlamalarında yada atamalarında kullanmak için ya iki tane ters bölü kullanılır yada atanan string değerinin önüne bu string bir literaldir ve olduğu gibi algılanmalıdır manasına gelen @ işareti konulur. Sanırım örneklerle konu daha iyi anlaşılacaktır.

Aşağıdaki atama C Sharp'ta hatalıdır. Çünkü ters bölü karakteri özel bir karakterdir ve compiler farklı yorumlamaya çalışır.

string klasor = "c:windows";

Aşağıdaki ifade doğrudur. compiler tarafında (tek ters bölü) olarak algılanır.

string klasor = "c:windows";

Yukarıdaki ifadenin yerine şu ifade de kullanılabilir. Aynı manaya gelir. işaretinin özel bir manaya gelmediğini ve tanımlanan string değişkeninin yazıldığı gibi olduğunu ifade eder.

string klasor = @"c:windows";

Regex ifadelerinde de işaretinin özel bir anlamı olduğu için c:windows ifadesiyle eşleşecek olan regex ifadesi aşağıdakilerden biri olmalıdır.

string klasor = "c:windows";
string klasor = @"c:windows";

İlk ifadedeki ters bölülerden iki tanesi C Sharp compiler tarafından kalanlardan biri de Regex compiler tarafından elenir diyebiliriz.

PHP ile Kurallı İfadeler

PHP, kurallı ifadeleri iki farklı şekilde ele almaktadır.

Perl uyumlu kurallı ifadeler klasik regex formatını kullanırlar:

/ / Bu tür kurallı ifadeler iki tane "/" işareti arasında gösterilirler.
  Karakterler ve karakterlerden oluşan bloklar kullanılır.
() Bloklar, "()" imleçleri arasında gösterilirler.
+ işleci sonuna geldiği karakter veya bloğun en az bir kere metin içinde geçtiğini anlatır.
* işleci sonuna geldiği karakter veya bloğun metin içinde sıfır veya daha çok kez geçtiğini anlatır.
? işleci sonuna geldiği karakter veya bloğun sıfır veya bir kere metin içinde geçtiğini anlatır.
{num1,num2} türü bir işleç sonuna geldiği karakter veya bloğun kaç kere metin içinde geçtiğini alt ve üst sınırlar vererek anlatır.
. newline ('n') dışında tüm karakterleri ifade eder.
s, tab (t) ve newline (n) dahil olmak üzere white space karakterlerini ifade eder.
S white space karakterler dışındaki tüm karakterleri ifade eder.
d 0-9 arası rakamları ifade eder
w harf, rakam ve '_' gibi bütün bir kelimeyi oluşturan karakterleri ifade eder.
W 'w' nin dışındaki karakterleri ifade eder.
^ cümle başlangıcını ifade eder
^ "[]" imleçleri arasında kullanılırsa seçimi tersine çevirir.
$ cümle bitişini ifade eder
b kelime başlangıç ve bitişleri için kullanılır.
[ ] imleçleri arasında rakam veya harf aralığı içinde kalan bir karakter ifade edilir.
| 'OR' içleci gibi çalışır.
Ters Bölü tüm bu özel karakterleri olduğu gibi yorumlanmasını sağlar

 

 

Class

Description

Expansion

[:alnum:]

Alphanumeric characters

[0-9a-zA-Z]
[:alpha:]

Alphabetic characters (letters)

[a-zA-Z]
[:ascii:]

7-bit ASCII

[x01-x7F]
[:blank:]

Horizontal whitespace (space, tab)

[ t]
[:cntrl:]

Control characters

[x01-x1F]
[:digit:]

Digits

[0-9]
[:graph:]

Characters that use ink to print (non-space, non-control)

[^x01-x20]
[:lower:]

Lowercase letter

[a-z]
[:print:]

Printable character (graph class plus space and tab)

[tx20-xFF]
[:punct:]

Any punctuation character, such as the period (.) and the semicolon (;)

[-!"#$%&'( )*+,./:;<=>?@[]^_`{|}~]
[:space:]

Whitespace (newline, carriage return, tab, space, vertical tab)

[nrt x0B]
[:upper:]

Uppercase letter

[A-Z]
[:xdigit:]

Hexadecimal digit

[0-9a-fA-F]

 

Regular expression (pattern)

Match (subject)

Not match (subject)

Comment
world Hello world Hello Jim Match if the pattern is present anywhere in the subject
^world world class Hello world Match if the pattern is present at the beginning of the subject
world$ Hello world world class Match if the pattern is present at the end of the subject
world/i This WoRLd Hello Jim Makes a search in case insensitive mode
^world$ world Hello world The string contains only the "world"
world* worl, world, worlddd wor There is 0 or more "d" after "worl"
world+ world, worlddd worl There is at least 1 "d" after "worl"
world? worl, world, worly wor, wory There is 0 or 1 "d" after "worl"
world{1} world worly There is 1 "d" after "worl"
world{1,} world, worlddd worly There is 1 ore more "d" after "worl"
world{2,3} worldd, worlddd world There are 2 or 3 "d" after "worl"
wo(rld)* wo, world, worldold wa There is 0 or more "rld" after "wo"
earth|world earth, world sun The string contains the "earth" or the "world"
w.rld world, wwrld wrld Any character in place of the dot.
^.{5}$ world, earth sun A string with exactly 5 characters
[abc] abc, bbaccc sun There is an "a" or "b" or "c" in the string
[a-z] world WORLD There are any lowercase letter in the string
[a-zA-Z] world, WORLD, Worl12 123 There are any lower- or uppercase letter in the string
[^wW] earth w, W The actual character can not be a "w" or "W"

 

Validating Usernames

Something often overlooked, but simple to do with a regular expression would be username validation. For example, we may want our usernames to be between 4 and 28 characters in length, alpha-numeric, and allow underscores.


$string = "userNaME4234432_";
if (preg_match('/^[a-zd_]{4,28}$/i', $string)) {
echo "example 1 successful.";
}

Validating Telephone Numbers

A much more interesting example would be matching telephone numbers (US/Canada.) We'll be expecting the number to be in the following form: (###)###-####


$string = "(032)555-5555";
if (preg_match('/^((?[2-9]{1}[0-9]{2})?|[0-9]{3,3}[-. ]?)[ ][0-9]{3,3}[-. ]?[0-9]{4,4}$/', $string)) {
echo "example 2 successful.";
}

Thanks to Chris for pointing out that there are no US area codes below 200.

Again, whether the phone number is typed like (###) ###-####, or ###-###-#### it will validate successfully. There is also a little more leeway than specifically checking for enough numbers, because the groups of numbers can have or not have parenthesis, and be separated by a dash, period, or space.



Email Addresses

Another practical example would be an email address. This is fairly straightforward to do. There are three basic portions of an email address, the username, the @ symbol, and the domain name. The following example will check that the email address is in the valid form. We'll assume a more complicated form of email address, to make sure that it works well with even longer email addresses.


$string = "first.last@domain.co.uk";
if (preg_match(
'/^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$/',
$string)) {
echo "example 3 successful.";
}

Postal Codes

Validating Postal codes (Zip codes?,) is another practical example, but is a good example to show how

?

works in regular expressions.


$string = "55324-4324";
if (preg_match('/^[0-9]{5,5}([- ]?[0-9]{4,4})?$/', $string)) {
echo "example 4 successful.";
}

What the

?

does in this example is saying that the extra 4 digits at the end can either not exist, or exist- but only once. That way, whether or not they type them in, it will still validate correctly.



IP Addresses

Without pinging or making sure it's actually real, we can make sure that it's in the right form. We'll be expecting a normally formed IP address, such as 255.255.255.0.


$string = "255.255.255.0";
if (preg_match(
'^(?:25[0-5]|2[0-4]d|1dd|[1-9]d|d)(?:[.](?:25[0-5]|2[0-4]d|1dd|[1-9]d|d)){3}$',
$string)) {
echo "example 5 successful.";
}

Hexadecimal Colors

Moving right along with numbers, we could check for Hexadecimal color codes, in short hand or long hand format (#333, 333, #333333 or 333333) with an optional # symbol. This could be useful in a lot of different ways... maybe previewing CSS files? Grabbing colors off pages? The options are endless.


$string = "#666666";
if (preg_match('/^#(?:(?:[a-fd]{3}){1,2})$/i', $string)) {
echo "example 6 successful.";
}

Multi-line Comments

- A simple way to find or remove PHP/CSS/Other languages multi-line comments could be useful as well.


$string = "/* commmmment */";
if (preg_match('/^[(/*)+.+(*/)]$/', $string)) {
echo "example 7 successful.";
}

Dates

- And my last simple, yet practical example would be dates, in my favorite MM/DD/YYYY format.


$string = "10/15/2007";
if (preg_match('/^d{1,2}/d{1,2}/d{4}$/', $string)) {
echo "example 8 successful.";
}

 

Kaynak

Yorumunuzu Ekleyin
Kurallı İfadeler (regex Engine) Yorumları +1 Yorum
  • Murat
    1
    Murat
    Cok güzel anlatmissiniz ancak android 5 chrome tarayicida ters bölülerin hiç biri gözükmüyor. Bilgisayarda denemedim. Onları düzeltebilirseniz çok güzel olur
    24 Nisan 2015 12:07:38, Cuma


Yükleniyor...
Yükleniyor...