3 puan yazan GN⁺ 2024-03-21 | 1 yorum | WhatsApp'ta paylaş

Python düzenli ifadelerinde "$" karakterinin davranışını anlamak

  • Python'un re modülü kullanıldığında, ^ işaretinin "dizenin başlangıcı", $ işaretinin ise "dizenin sonu" anlamına geldiği bilinir.
  • Ancak $ her zaman yalnızca "dizenin sonu" anlamına gelmez ve davranışı platforma göre değişebilir.
  • Python'da çok satırlı mod devre dışıyken, $ karakteri dizenin sonuna veya dizenin sonundaki satır sonu karakterinden hemen önce eşleşebilir.

Dize sonu ve satır sonu karakteri eşleşmesi arasındaki fark

  • Çok satırlı mod devre dışıyken Python'da satır sonu karakteri olmadan dizenin sonuna eşleşmek için yalnızca $ kullanmak yeterli değildir.
  • Dizenin sonuna eşleşmek için \z ve \Z kullanılabilir.
  • Python'da re.MULTILINE kullanıldığında $, dizenin sonuna ve her satırın sonuna (satır sonu karakterinden hemen önce) eşleşir.

Farklı platformlarda düzenli ifade davranışlarının karşılaştırılması

  • Çeşitli platformlarda cat\n için desen eşleşmesinin karşılaştırıldığı tablo, satır sonu karakterini içerecek şekilde eşleşmeye izin veriliyorsa çok satırlı modda $ kullanmanın tutarlı davrandığını gösteriyor.
  • Satır sonu karakterini dahil etmeden eşleşmek için Python ve ECMAScript dışındaki tüm platformlarda \z kullanılmalı; Python ve ECMAScript'te ise sırasıyla \Z veya çok satırlı mod olmadan $ kullanılmalıdır.

GN⁺ görüşü

  • Bu yazı, düzenli ifade kullanan geliştiricileri Python'da $ karakterinin beklenmedik davranışı konusunda uyarabilir.
  • Düzenli ifadeler dize işleme için son derece güçlüdür; ancak platforma göre farklı davranabildikleri için dikkat gerektirir.
  • Geliştiricilerin bu farkları bilmesi ve çapraz platform uygulamaları geliştirirken uyumluluk sorunlarından kaçınmak için ek testler yapması gerektiği vurgulanıyor.
  • Benzer işlevler sunan diğer düzenli ifade kütüphaneleri arasında Java'nın java.util.regex ve .NET'in System.Text.RegularExpressions kütüphaneleri yer alır; bunlarda da platforma özgü davranış farkları anlaşılmalı ve buna göre kullanılmalıdır.
  • Yeni bir düzenli ifade sözdizimi veya davranışı benimsenirken mevcut kodla uyumluluk, performans etkisi ve ekip içindeki öğrenme eğrisi dikkate alınmalı; bu değişikliklerin getireceği fayda ve maliyet iyi değerlendirilmelidir.

1 yorum

 
GN⁺ 2024-03-21
Hacker News görüşleri
  • Düzenli ifadelere aşina olanlar, ^ işaretinin "string'in başlangıcı"nı ve $ işaretinin "string'in sonu"nu ifade ettiğini bilir. Ama ben şahsen bunları "satırın başlangıcı" ve "satırın sonu" olarak düşünüyorum. Çoğu durumda metni satır satır işlediğimiz için sonuç aynıdır, ancak bu operatörleri düşünme biçimim değişmiyor. Muhtemelen düzenli ifadelerle ilk kez grep üzerinden tanıştığım ve girdiyi esas olarak "satır" olarak düşündüğüm içindir.

    • POSIX düzenli ifadeleri ile Python düzenli ifadeleri farklıdır. Genelde kullandığınız implementasyonun düzenli ifade belgelerine bakmanız gerekir; söz dizimi evrensel değildir.
    • POSIX Bölüm 9'a göre düzenli ifadeler genellikle metin işleme ile ilişkilidir ve sonu string'in bittiğini gösteren NUL ile biten string'ler üzerinde çalışır. Bazı yardımcı araçlar işlemeyi satır düzeyiyle sınırlar. $ işareti string'in sonuna da satırın sonuna da karşılık gelebilir; bu, kullanılan araca (veya moda) göre tanımlanır. Çoğu yaygın araç (grep, sed, awk, Python vb.) varsayılan olarak bunu satır sonu olarak ele alır.
    • Tek, evrensel bir düzenli ifade söz dizimi yoktur. Hangi dili ve seçenekleri kullandığınızı bilmeden düzenli ifadeleri güvenilir biçimde okuyup yazamazsınız.
  • Robert Elder'dan bahsetmek için mükemmel bir fırsat. YouTube ve blog içeriği üretiyor, düzenli ifadeler hakkında bir serisi var ve farklı araçların davranış farklarını derinlemesine inceliyor.

  • Düzenli ifadeler, Perl'i ilk öğrenirken gerçekten içselleştirdiğim ilk şeylerden biriydi. (Perl'in hâlâ "Camel" kitabı sayesinde kalbimde sıcak bir yeri var)

    • Bugün en önemli bilgi, implementasyonların farklı olduğunu bilmek ve üzerinde çalıştığınız şeyin referans belgelerine başvurma alışkanlığı edinmek.
    • Örneğin Emacs düzenli ifadeleri, karakter sınıfı olarak "\w" yerine "\s_-" kullanır (ya da referansa bakmadan ekranda ona benzer bir şey); ama Emacs dokümantasyon ve keşfedilebilirlik konusunda en iyilerden biridir.
    • Bazı araçlar parantezlerin escape edilmesini ister, bazıları istemez. Bazen bu davranış yapılandırılabilir, bazen değildir.
    • Kafa karışıklığı, can sıkıntısı ve inkâr aşamalarının hepsinden geçtim; artık sadece kabul ediyorum. Kavram her yerde aynı ama çeşnisi değişiyor.
  • Kötü işe alım yöneticilerinin, "Düzenli ifadelerde string'in sonu nasıl eşleştirilir?" sorusunu "Hah! Demek bu tuzağı bilmiyordun!" soruları listesine eklediğini duyabiliyorum.

  • Düzenli ifadeler söz konusu olduğunda Perl'i listeden çıkarmak garip.

    • perlre belgelerinde $ için açıklama: string'in sonuyla eşleşir (veya string sonundaki satır sonu karakterinden önce; ya da /m kullanılıyorsa her satır sonu karakterinden önce)
  • Raku (eski adıyla Perl 6), string'in başlangıcı ve sonunu göstermek için ^ ve $ işaretlerini seçiyor; satırın başlangıcı ve sonu için ise ^^ ve $$ ekliyor. Çok satırlı mod ya yok ya da gerekli değil.

    • Tam bir yeniden düşünme/yeniden yazmanın avantajlarından biri, önceki davranışın insanları şaşırttığı gerçeğinden ders çıkarabilmek.
  • Düzenli ifadelerin standartlaştırıldığını düşünen biri var mı? Yeni bir bağlama geçmek her zaman yeniden öğrenme süreci.

  • String ve satır konusunda bir karışıklık var. String, karakterlerin bir dizisidir; satır ise iki farklı şey olabilir. Satır sonu karakterini satır sonlandırıcı olarak görürseniz, satır satır sonu karakterini de içeren, satır sonu olmayan karakterlerin bir dizisidir. Satır sonu karakteri yoksa bu tam bir satır değildir. POSIX'in kullandığı yaklaşım budur. Satır sonu karakterini satır ayırıcı olarak görürseniz, satır satır sonu olmayan karakterlerin bir dizisidir. Her iki durumda da satırın içeriği satır sonu karakterinden önce biter; çünkü o karakter ya satırı sonlandırır ya da bir sonraki satırdan ayırır.

    • ^ ve $ işaretlerinin anlamı, tek satırlı veya çok satırlı mod olmasına bakılmaksızın satıra dayanır. String tabanlı anlam için — dosyalarla çalışırken bunu tüm dosya olarak da düşünebilirsiniz — \A ve \Z ya da bunların karşılıkları kullanılır.
  • Bu, Ruby tabanlı uygulamalarda birkaç ciddi hataya yol açtı. Ben hep \A\z kullanıyorum.