regular expression etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
regular expression etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

11 Mart 2019 Pazartesi

Düzenli İfadeler (Regular Expressions) ile Positive Lookbehind - Belli Karakter İle Başladığı

Giriş
Bu düzenli ifadeye (?<=subexpression) şeklinde yazılır. Positive lookbehind parantez içinde yazılmasına rağmen düzenli ifadedeki eşlemeye dahil edilmez. Yani non-consuming kabul edilir. Açıklaması şöyle.
For a match to be successful, subexpression must occur at the input string to the left of the current position, although subexpression is not included in the match result. A zero-width positive lookbehind assertion does not backtrack.

Zero-width positive lookbehind assertions are typically used at the beginning of regular expressions. The pattern that they define is a precondition for a match, although it is not a part of the match result.
Lookbehind + Lookahead Birlikte Kullanılırsa
Lookbehind + X + Lookahead şeklinde kullanılırsa x'leri capture eder.

Örnek - Lookbehind + Lookahead
Elimizde şöyle bir kod olsun. Önünde sayı, ardında yine bir sayı olan boşlukları siler.
string test = "Some Words 1 2 3 4";
string result = Regex.Replace(test, @"(?<=\d)\s+(?=\d)", "");
Çıktı olarak şunu alırız.
Some Words 1234
Örnek - Lookbehind + Lookahead
Elimizde şöyle bir kod olsun.
"(?<=[a-z])(?=[A-Z])|(?<=[0-9])(?=[A-Za-z])|(?<=[A-Za-z])(?=[0-9])|(?<=\\W)(?=\\W)");
Açıklaması şöyle. Split için boundary bulmak istersek önünce örneğin rakam, arkasında harf olan karakteri bulabiliriz.
what precedes is a lowercase, and what follows is an uppercase (or vice-versa)
what precedes is a digit and what follows is a letter (or vice-versa)
what precedes and what follows is a non word character (e.g. quote, parenthesis, etc.)
Örnek - Lookbehind + Lookahead
Kotlin'de şöyle yaparız. Arkasında x önünde o olarak veya Arkasında o önünde x olan yerlerden böler.
val str = "xxoooooooxxoxoxooooo"
val reg = Regex("(?<=x)(?=o)|(?<=o)(?=x)")
var list = str.split(reg)
println(list) 
// => [xx, ooooooo, xx, o, x, o, x, ooooo]

25 Şubat 2019 Pazartesi

Düzenli İfadeler (Regular Expressions) ile Positive Lookahead

Giriş
Düzenli ifadeye (?=subexpression) şeklinde yazılır. Positive lookahead parantez içinde yazılmasına rağmen düzenli ifadedeki eşlemeye dahil edilmez. Yani non-consuming kabul edilir. Açıklaması şöyle.
Typically, a zero-width positive lookahead assertion is found at the end of a regular expression pattern. It defines a substring that must be found at the end of a string for a match to occur but that should not be included in the match. It is also useful for preventing excessive backtracking.
Örnek
Elimizde şöyle bir kod olsun. Önünde sayı, ardında yine bir sayı olan boşlukları siler.
string test = "Some Words 1 2 3 4";
string result = Regex.Replace(test, @"(?<=\d)\s+(?=\d)", "");
Çıktı olarak şunu alırız.
Some Words 1234
Örnek
Artarak giden 5 tane rakamı yakalamak için şöyle yaparız.
^\d*(?=\d{5}(\d*)$)0?1?2?3?4?5?6?7?8?9?\1$
Açıklaması şöyle.
We can force it to match exactly 5 characters by combining a look-ahead of five digits and an arbitrary suffix (which we capture) and a backreference \1 (which must exactly the suffix matched by the look-ahead, ensuring we've now walked ahead 5 characters in the string).
Örnek
Belli bir kelimeye kadar olan grubu yakalamak için şöyle yaparız.
/^.+?(?=\s*\b(?:was|in|for)\b)/
Elimzde "Once upon a time there was a fox in a hole";  olsun
Souç olarak şunu alırız
"Once upon a time there"

8 Ekim 2014 Çarşamba

C# Regex örnekleri

Giriş
RegEx sınıfını bir türlü tam olarak kullanmayı öğrenemedim. Kaç tane yazı yazdım hiçbirisi hoşuma gitmedi. C# için yeni bir yazı başlatıyorum.

Repeated Characters
Tekrar eden karakterleri bulmak için (.)\1 kullanılır.
Örnek'te tekrar eden karakterler bulunuyor ve karakter + tekrar eden karakter sayısı şeklinde yazılıyor. Regex.Replace metoduna verilen 3. parametre bir MatchEvaluator delegate. Bu delegate her math eden örüntünün neyle değiştirileceğini döner. Yani bir string dönmek zorunda.

public static string Compress(string str) {
  return Regex.Replace(str, @"(.)\1*", m => m.Groups[1].Value + m.Value.Length);
}

    



5 Temmuz 2014 Cumartesi

Düzenli İfade Örnekleri

Bazı düzenli ifade örneklerini aşağıya ekledim.

Düzenli İfadelerde Kullanılan Özel Karakterler Sınıfları
Özel karakter sınıfları belli bir kümedeki karakterlerle eşleşirler
Basit bir şekil aşağıda.

Harfler

[a-z] aralığında boşluk karakteri (space) de aralığa dahildir.

Sayılar
\d ile bir sayı karakteri ifade edilir.

\D ile sayı olmayan bir karakter ifade edilir.
Örnekte "046 55.5" şeklindeki bir telefon numarası non-digit karakterler silinerek "046555" haline getiriliyor.
Regex.Replace(value, @"\D", "") 

Boşluk
\s ile boşluk (space) karakteri ifade edilir. Anladığım kadarıyla \t (tab) karakteri de boşluk olarak kabul ediliyor.

Boşluk olmayanlar 
 \S ile space olmayan karakterler ifade edilir. Örneğin (\S+)\s+(.+?) ile space olmayan bir grup, sonra bir veya daha fazla boşluk, sonra ise yakalamak istediğimiz grubu buluruz. Space olmayan karakterleri [^\\s] şeklinde de ifade edebileceğimizi sanıyorum. 

Kelime
\w ile bir word (kelime) ifade edilir. [A-Za-z0-9_] ifadesinin kısa halidir. string.replaceAll java doesn't work with lookaround regex? örneğinde \w ifadesine { karakterinin dahil edilmediği görülebilir. 

Kelime Olmayanlar
\W \w kısaltmasının tam tersini yapar. Yani alfanümerik olmayan imla işareti gibi "," ";" "." gibi karakterleri bulur.

Çapalar (Anchor)
Çapalar ile düzenli ifade moturu bir sonraki karakteri işlemez. Ama koşulun tutup tutmadığını değerlendirir.

\b ile word boundary ifade edilir. Örneğin \bcat\b ifadesi ile The cat scattered his food all over the room. cümlesinde sadece cat kelimesi ile eşleşilir.
\B \b kısaltmasının tam tersini yapar
^ ile string'in başı belirtilir. Multiline modu kullanılmıyorsa cümle içinde \n karakterini dikkat almaz.

Quantifiers 

Grubun Uzunluğunu Kontrol Etme Örnekleri
0 ila 11 tane arasında olması gerektiğini belirtmek için \d{0,11} yazıyoruz. Tamı tamına 11 tane olması için \d{11} yazıyoruz. Bir başka örnek ise burada.

Eğer bir quantifier  bir kaç defa tekrar edecekse örneğin, parantez içine alma gerekebilir. Örnek:
^(\d{1}){2} // iki defa tekrar etsin
Greedy

Düzenli ifadeler default olarak greedy çalışırlar. Örneğin \s+ ile azami eşleşme yapılırken \s+? ile reluctant çalışması sağlanır. Yani ? işareti greedy çalışmayı engeller.

Escape yapılması gereken özel karakterler
  • { karakteri aslıda "kaç tane"anlamına gelen kısaltma olduğu için - örneğin \d{2}'nin escape ile işaretlenmesi gerekir. Dolayısıyla \d\\{2 şeklinde yazılmalı.
İçerildiğini Bulma Örnekleri
Bir ifadenin içerildiğini bulmak
".*true.*" örneğinde string içinde true kelimesinin geçip geçmediği geçtiği bulunabilir.

Bir veya birkaç karakterin içerildiğini bulmak
.*[x-z].* örneğinde x-z arasındaki (her ikisi de dahil) herhangi bir karakterin içerildiği kontrol edilir.

Bir ifade ile başlanılmadığını bulmak
"^[^\\d].*" örneğinde string'in sayı ile başlayıp başlamadığı bulunabilir

İçeriği Yakalama Örnekleri
Bir ifade ile başlamak ve geri kalanı yakalamak





24 Mayıs 2013 Cuma

Düzenli İfadeler (Regular Expressions) ve Programlama Dilleri

Düzenli ifadeler bana her zaman çok karışık gelmiştir. Aşağıda bazı notlarım var.

Tamamen Eşleşme
boost
boost::regex_match ile verilen string'in tamamının düzenli ifadeyle uyuşup uyuşmadığı kontrol edilir. Aşağıda bu durum açıklanmış.

Örnek
#include <boost/regex.hpp>
boost::regex e ("my pattern");
if ( regex_match ("toFind", e ) )
{
    //Yes...
}
Java
String.matches(String regex) ile eşleşme kontrol edilir.

Tamamen Eşleşme ve Yakalama
boost match_result sınıfının first() ve second() metodları ile iterator kullanma
Bir diğer örnek ise tamamen eşleşme ve verilen string içindeki alanların yakalanması. Örneği boost'un kendi sayfasından aldım.Yakalama için match_result sınıfı kullanılır.Bu sınıfın first ve second metodları ile yakalanan string'e işaret eden iterator'lere erişilebilir.


Arzu edilirse eşleşen alanlar üzerinde döngüyle de dolaşılabilir. Döngünün 1'den başladığına dikkat etmek lazım.

Yakalamak için boost içinde boost::smatch what veya boost::cmatch what gibi iki farklı yapının kullanıldığını gördüm ama aralarındaki fark nedir bilmiyorum.

boost match_result sınıfının prefix() ve suffix() metodlarını kullanma
Aşağıdaki örnekte eşleşme yapılan grubun ön ve sonundaki stringleri alabilme imkanı var.



boost match_result sınıfının str() metodunu kullanma
Yukarıdaki örnekte eşleşmeyi bir string içine almak için first(), second() metodlarını kullandık. Aşağıdaki örnekte ise eşleşmeyi direkt string olarak almak için str() metodunu kullanıyoruz.
 
Java
Aşağıda ilginç bir örnek gördüm. Yakalama grubuna $1 ile erişmiş.

 
Kısmi Eşleşme
C++
C++ 11 regex: checking if string starts with regex sorusunda da gösterildiği gibi regex_search ile yapılır.
std::regex_constants::match_continuous bayrağı verilen string'in düzenli ifade ile başlaması gerektiğini belirtir.

boost regex_search (İlk eşleşme)
regex_search ile yapılır. Bu metod ile match_result sınıfı aracılığıyla eşleşme yapılan string'i alabilme imkanı vardır. İstenmezse sadece metodun döndürdüğü değere de bakılabilir.

Burada dikkat edilmesi gereken nokta smatch veya cmatch yapısı regex_search sınıfına geçilen string'e pointer tutuyorlar. Eğer C++ regex string capture sorusundaki gibi metoda temporary string geçersek hata yapmış oluruz.
smatch sm1;
regex_search(string("abhelloworld.jpg"), sm1, regex("(.*)jpg"));//hata...
cout << sm1[1] << endl;
Java
Buradaki soruda açıklandığı gibi string içindeki tüm sayıları almak için aşağıdaki örnek kullanılabilir.group() metodu ile eşleşmeyi sağlayan tüm string alınabilir.
Bir diğer örnekte ise WWW ile başlayıp : ile biten patern yakalanıyor.


Kısmi Eşleşme ve Yakalama
boost sregex_iterator - Yakalama Grubuna Sayı ile Erişme
sregex_iterator iterator sınıfı ile verilen string üzerinde döngü kurmak çok kolay. How do I loop through results from std::regex_search? sorusunda açıklandığı gibi tüm kısmi eşleşmeleri almak için aşağıdaki gibi bir kod lazım.

Java - Yakalama Grubuna Sayı ile Erişme
Aşağıdaki örnekte kısmi eşleşme sağlayan tüm parçalar döngü içinde alınabilir. Aşağıda group(1) metodunun çağırılmasının sebebi group(int) metodunda şöyle açıklanmış.
Capturing groups are indexed from left to right, starting at one. Group zero denotes the entire pattern, so the expression m.group(0) is equivalent to m.group(). 
Eğer capturing gruplama yapılmıyorsa Matcher sınıfının start() ve end() metodları kullanılabilir.
Pattern p = Pattern.compile("[A-Z]+");
Matcher m = p.matcher(data);
List<String> sequences = new ArrayList<String>();
while (m.find()) {
    sequences.add(data.substring(m.start(), m.end()));
}

Case Insensitive Çalışma
boost
  boost::regex regex ("your epxression here",boost::regex::icase);
C#
Regex r = new Regex(@"your epxression here", RegexOptions.IgnoreCase);
Java
Java ile case insensitive çalışma için düzenli ifadeye (?i) karakterini eklemek lazım. Örnek:
Ancak bu seçenek sadece ASCII kodları için çalışıyor. Eğer Unicode karakterler de bulunsun isteniyorsa (?ui) karakterlerini kullanmak lazım.
Tüm Eşleşmeleri Alma
C#
Regex sınıfı yazısına taşıdım.

Java
C#'taki kadar kolay olmasa da yukarıdaki örneklerde görüldüğü gibi döngü ile dönerek tüm eşleşmeleri alma işlemi yapılabiliyor. Matcher sınıfının find metodu kullanılırken metodun çalışma şekline dikkat etmek lazım. Açıklamadan da görüldüğü gibi Matcher sınıfı bir önceki aramada nerede kaldığını hatırlıyor.

  
Birden Fazla Satır İle Çalışma
Java
Eşleşen İfadeyi Başka Bir String İle Değiştirme 
C++ 
regex_replace ile yapılır.
regex rx("world.*");
regex_replace("hello world hello", rx, "myworld");//çıktı olarak hello myworld verir

 

30 Ocak 2013 Çarşamba

Düzenli İfadeler (Regular Expressions) ile İleriye ve Geriye Bakma

Düzenli ifadelerde ileriye ve geriye bakma kabiliyeti çok lazım olan şeylerden birisi. Nasıl yapıldığını anlatan gördüğüm en iyi site burası.

Buradaki sorudan da anlaşıldığı gibi ileri ve geri bakma kabiliyeti bi-directional iterator kullanılmasını gerektiriyor.

İleriye Bakma
Peki bu yetenek neden lazım ? Şöyle bir örnek vereyim. Diyelim ki virgül ile biten sayıları arıyoruz, ancak virgül karakterinin arama sonucunda dönmesini istemiyoruz. Eğer ileri bakma yeteneği olmasaydı bu aramayı yapamazdık. Bu gibi durumlar için düzenli ifadelerdeki positive lookahead, negative lookahead, positive lookbehind ve negative lookbehind kabiliyeti kullanılıyor. Bu yeteneklere hepsine kısaca lookaround deniyor.

Lookahead için ? işareti, lookbehind içinse ?< işareti ile başlayan düzenli ifadeler kullanılır.

Positive Lookahead : İleriye bakarak verilen düzenli ifadeyle bittiğinin kontrol
Positive Lookahead yazısına taşıdım.

Negative Lookahead : İleriye bakarak verilen düzenli ifadeyle bitmediğinin kontrolü
Düzenli ifadeye (?! ile başlayan bir ek yapılır. RegEx to extract the first 6 to 10 digit number, excluding 8 digit numbers  örneğinde
ifadesi için negative lookahead kullanılmış.



Geriye Bakma

Negative LookBehind - Geriye bakarak verilen düzenli ifade ile başlamadığının kontrolü
Düzenli ifadeye  (?<! ile başlayan bir ek yapılır. How do I properly use negative lookahead for this Java regex? sorusundan aldığım örnek aşağıda.
Bir başka örnek ise burada.
Bu örnekte 3 haneli bir sayının &# karakterleri ve alfanümerik bir metin ile başlamadığı kontrol edilir.

Bir diğer örnekte ise  "-" karakteri başlamayan boşluk karakteri ayrılıyor.


Positive LookBehind
Positive Lookbehind yazısına taşıdım