2.35. Desen temelleri¶
Bir düzenli ifade, dizeleri tam içeriklerine göre değil biçimlerine göre tanımlamak için kullanılan küçük bir dildir. Bir dize, ancak ve ancak tanımlayabildiğiniz ama sıralayamadığınız bir desene uyuyorsa eşleşiyorsa onu kullanın – “bir birim ile takip edilen rakam dizisi”, “ERROR ile başlayan ve bir sayıyla biten bir satır”, “bu dosya uzantılarından herhangi biri, herhangi bir sırada, isteğe bağlı v önekleriyle”.
re modülüne yalnızca sade bir dize metodu işe yaramadığında başvurun.
str.startswith(),str.endswith()– sabit bir önek veya sonek için test.in– sabit bir alt dizenin mevcut olup olmadığını test etme.str.split(),str.find(),str.replace()– sabit sınırlayıcılarla çalışma.
Bunların her biri eşdeğer regex’ten daha hızlı, okunması daha kolay ve yanlış yapması daha zordur. Dizenin biçimi önemli olduğunda ve tam alt dize önemli olmadığında regex kullanın.
2.35.1. Kullanacağınız dört şey¶
MicroPython re modülü dört şey sunar:
re.compile()– bir desen dizesini yeniden kullanabileceğiniz derlenmiş bir desen nesnesine dönüştürür.re.match()– deseni bir dizenin başlangıcında dener. Desen 0. konuma sabitlenir.re.search()– deseni bir dizede herhangi bir yerde dener. İlk eşleşmeyi döndürür.re.sub()– her eşleşmeyi bulur ve değiştirir.
CPython’a kıyasla dikkat çekici eksiklikler: re.findall yok, re.finditer yok, modül düzeyinde re.split yok (bunun yerine derlenmiş desenlerin bir split metodu vardır), re.fullmatch yok, re.IGNORECASE gibi bayrak sabitleri yok. CPython’da bunlardan birine başvuracağınız yerde, eşdeğerini bir döngü içinde re.search() ile oluşturun.
2.35.2. İlk desen¶
r'\d+' deseni bir veya daha fazla rakamı eşleştirir:
>>> import re
>>> m = re.search(r'\d+', 'sensor reading 42 ok')
>>> m.group(0)
'42'
Dikkat edilecek birkaç şey:
Desen bir ham dize (
r'...') olarak yazılır, böylece\diçindeki ters eğik çizgi bir Python dize kaçışı olarak işlenmek yerineremodülüne ulaşır. Regex desenleri için her zaman ham dizeler kullanın.re.search()başarı durumunda bir eşleşme nesnesi ve başarısızlık durumundaNonedöndürür.match.group()çağrılmadan önce her zaman kontrol edin.m.group(0)desenin eşleştirdiği tam metindir. Grup 1, 2, … desen yakalama parantezleri içerdiğinde daha sonra ortaya çıkar.
Aynı desen re.match() ile None döndürür çünkü dize bir rakamla başlamaz
>>> re.match(r'\d+', 'sensor reading 42 ok') is None
True
>>> re.match(r'\d+', '42 readings')
<match num=1>
2.35.3. Bir desenin parçaları¶
En kullanışlı desenler küçük bir parça kümesinden oluşturulur. MicroPython’da çalışanlar:
Değişmez karakterler – özel olmayan herhangi bir karakter kendisiyle eşleşir. hello, hello ile eşleşir.
Özel karakterler – . ^ $ * + ? { } [ ] \ | ( ) karakterlerinin tümünün aşağıda belirtilen anlamları vardır. Bunlardan birini değişmez olarak eşleştirmek için bir ters eğik çizgiyle kaçış yapın: \. değişmez bir noktayı eşleştirir.
Karakter sınıfları – yaygın karakter kümeleri için kısaltmalar:
\d– herhangi bir0-9rakamı\D– rakam olmayan herhangi bir karakter\s– herhangi bir boşluk karakteri (boşluk, sekme, satır sonu)\S– boşluk olmayan herhangi bir karakter\w– herhangi bir “sözcük” karakteri: harfler, rakamlar, alt çizgi\W– sözcük olmayan herhangi bir karakter.– satır sonu hariç herhangi bir karakter
Niceleyiciler – önceki parçanın kaç kez eşleşmesi gerektiği:
*– sıfır veya daha fazla (açgözlü)+– bir veya daha fazla (açgözlü)?– sıfır veya bir{n}– tam olarak n{m,n}– m ile n arasında (dahil)
Birleştirme: \d{3}-\d{4} üç rakam, bir tire, dört rakamı eşleştirir. \s+ bir veya daha fazla boşluk karakterini eşleştirir. hello.*world, hello, herhangi bir şey (hiçbir şey dahil), ardından world‘ü eşleştirir.
Not
Açgözlü, niceleyicinin desenin geri kalanının yine de eşleşmesine izin verirken girişin mümkün olduğunca çoğunu tüketmesi anlamına gelir. hello x world y world dizesine karşı, hello.*world içindeki .*, sonda bir world bırakan en uzun diziyi eşleştirir – daha kısa olan x‘i değil, x world y‘yi yakalar. Aynı durum + ve {m,n} aralık biçimi için de geçerlidir: motor yapabileceği en uzun eşleşmeyi alır, ardından yalnızca desenin geri kalanı başarısız olursa geri çekilir.
2.35.4. Değiştirme¶
re.sub() her eşleşmeyi bulur ve onu bir dizeyle değiştirir. Değiştirme, \1, \2, … aracılığıyla yakalanan gruplara başvurabilir (grup sözdiziminin geri kalanıyla birlikte daha sonra ele alınır). Gruplar olmadan re.sub bir regex üzerinde doğrudan bir bul-değiştir işlemidir:
>>> re.sub(r'\s+', ' ', 'too many spaces')
'too many spaces'
>>> re.sub(r'\d+', 'N', 'log 12, log 345, log 6')
'log N, log N, log N'
Üçüncü argüman üzerinde çalışılacak dizedir; sonuç, her eşleşmenin değiştirildiği yeni bir dizedir.
2.35.5. Bölme – yalnızca derlenmiş bir desende¶
Modül düzeyinde re.split yoktur. Bir regex üzerinde bölmek için, deseni önce derleyin ve onun split metodunu çağırın:
>>> sep = re.compile(r'\s*,\s*')
>>> sep.split('a , b,c , d')
['a', 'b', 'c', 'd']
İsteğe bağlı ikinci argüman bölme sayısını sınırlar:
>>> sep.split('a, b, c, d', 2)
['a', 'b', 'c, d']
2.35.6. Yeniden kullanım için derleme¶
Aynı desen birçok kez çalışıyorsa – bir döngü içinde veya sık çalışan bir fonksiyonda – onu bir kez derleyin ve derlenmiş nesneyi yeniden kullanın:
digit_run = re.compile(r'\d+')
def first_number(line):
m = digit_run.search(line)
return int(m.group(0)) if m else None
Derlenmiş bir nesnede pattern.match() ve pattern.search() çağrılması, modül düzeyindeki fonksiyonlarla aynıdır ancak her çağrıda yeniden derleme maliyetini atlar.
2.35.7. Hiçbir şeyle eşleşmeyen desenler¶
Özellikle üç desen geliştiricileri yanıltır:
.*boş dizeyle eşleşir.re.search(r'.*', s).group(0)herhangi bir girişte''döndürür.Kaçış yapılmamış özel karakter içeren bir desen bir sözdizimi hatasıdır.
re.compile(r'cost: $5'),$“dizenin sonu” anlamına geldiği içinValueErrorfırlatır.r'cost: \$5'kullanın.Nokta
.bir satır sonuyla eşleşmez. Satır sonları boyunca eşleştirmek için, deseni bunları açıkça işleyecek şekilde[\s\S]ile yazın veya her seferinde bir satır besleyin.
Bu parçalarla bir desen, metnin neredeyse herhangi bir sabit biçimli dilimini eşleştirebilir. Yapısal veriyi eşleşmeden geri çekmek yakalama grupları gerektirir.