ProgramlamaBackend geliştirici

Perl'de s/// formatında düzenli ifadelerle nasıl çalışılır: açgözlü ve tembel kalıplar arasındaki farklar, çok satırlı dizelerin nasıl düzgün işlenmesi gerektiği ve beklenmedik etkilerden nasıl kaçınılır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Perl, düzenli ifadelerin derin düzeyde entegre edildiği dillerden biridir. Ana değiştirme operatörü s///, şablona göre dize parçalarını arayıp değiştirmeye olanak tanır. Bu yapının içinde, açgözlü/tembel kalıplar, çok satırlı işleme ve değiştirme seçenekleri gibi çok sayıda ince nokta bulunmaktadır.

Sorunun Tarihçesi

s/// operatörü, Perl'in erken sürümlerinden beri bulunmaktadır ve Perl, daha sonra diğer diller tarafından benimsenen düzenli ifadelerin sözdiziminin temellerini atmıştır. Şablonların ve değiştiricilerin (g, m, s, i, x vb.) çoğu, özellikle Perl'de ortaya çıkmış ve gelişmiştir.

Problem

Pratikte birçok geliştirici açgözlü kantitatörleri yanlış kullanmakta veya değiştiricilerde (özellikle s ve m) karışıklık yaşamaktadır, bu da çok satırlı metinlerde veya büyük verilere yapılan değişikliklerde beklenmedik sonuçlara yol açmaktadır. Hatalar, bir dizide bir eşleşme beklenirken başka birinin alınması ya da sadece ilk/son eşleşmelerin değiştirilmesi durumunda meydana gelmektedir.

Çözüm

Şablonları doğru seçmek ve ayarlamak ve değiştiricilerin etkisini anlamak önemlidir. Açgözlü kalıplar (örneğin, .*) mümkün olan en geniş aralığı kapsar, tembel kalıplar (örneğin, .*?) ise gerekli olan en dar aralığı kapsar.

Değiştiricilerle çalışma:

  • g — tüm eşleşmeler için değişiklik gerçekleştirilir
  • s — çok satırlı dizelerin işleme modunu etkinleştirir, burada nokta (.) satır sonu karakterini yakalar
  • m — ^ ve $ işaretlerinin davranışını değiştirir

Örnek — <tag> ... </tag> etiketlerini her seferinde yalnızca bir etiket için boşluk ile değiştirmek (tembel):

my $text = 'a <tag>1</tag> <tag>2</tag> b'; $text =~ s/<tag>.*?<\/tag>//g; print $text; # a b

Çok satırlı dizelerin işlenmesi için:

my $data = "Line 1 Line 2 <tag> DATA </tag> End"; $data =~ s/<tag>.*?<\/tag>//gs; print $data;

Temel özellikler:

  • Açgözlü kalıplar en geniş aralığı kapsar, tembel kalıplar en dar aralığı
  • s değiştiricisi, noktanın (.) satır sonlarını yakalamasını sağlar
  • g değiştiricisi, yapılan değişikliklerin sayısını etkiler

Kandırıcı Sorular.

Açgözlü .*'den sonra? belirtilmezse birden fazla etiket işlenirken ne olur?

Açgözlü kantitatör, mümkün olan en geniş aralığı kapsar, bu da ara etiketlerin de dahil edilmesine neden olur ve bu da ilk <tag> ve son </tag> arasındaki her şeyi beklenmedik bir şekilde siler:

my $txt = 'A <tag>1</tag> <tag>2</tag> B'; $txt =~ s/<tag>.*<\/tag>//g; print $txt; # A B

Burada, ilk <tag> ile son </tag> arasındaki tüm parça değiştirilmiştir.

Perl düzenli ifadelerinde m ve s değiştiricisi arasındaki fark nedir?

s — nokta (.) yeni satır karakterini yakalar; m — çok satırlı metin içinde satır başları ^ ve $ için çalışma şeklini değiştirir. Amaçları farklıdır, ancak sıklıkla karıştırılırlar.

my $s = "abc def"; # /^def/ m olmadan çalışmaz print $s =~ /^def/m; # 1 (doğru)

s///'yi yalnızca bir kez uygularsam, tüm eşleşmeleri nasıl işlerim?

g değiştiricisi yoksa yalnızca ilk eşleşme değiştirilir. Küresel değiştirme için g eklemek gerekir:

my $s = "foo bar foo"; $s =~ s/foo/baz/g; # her iki foo 'yu değiştirir

Tipik Hatalar ve Anti-Desenler

  • Tembel kalıpların gerektiği yerlerde açgözlü kalıpların kullanılması, gereksiz verilerin yakalanmasına yol açar
  • Yalnızca ilk eşleşmenin değiştirildiği için gözden kaçırılan g değiştiricisi
  • Çok satırlı verilerle çalışırken s ve m değiştiricilerinin göz ardı edilmesi

Gerçek Hayattan Bir Örnek

Olumsuz Durum

Geliştirici HTML etiketleri için bir değiştirme işlemi yazdı:

$text =~ s/<tag>.*<\/tag>//g;

Sonuç olarak, metinden tüm etiketler ve arasındaki içerikler kesilir — her bir etiket ayrı ayrı değil.

Artıları:

  • Kısa ve anlaşılır kod
  • Tek bir eşleşme için hızlı işlem

Eksileri:

  • Benzer birçok parçanın yanlış sonuç vermesi
  • Kalan yapının bütünlüğünün bozulması

Olumlu Durum

Tembel kalıp ve doğru değiştiricileri kullanmak:

$text =~ s/<tag>.*?<\/tag>//gs;

Artıları:

  • Her blok doğru bir şekilde değiştirilir
  • Gereksiz yakalamalar yoktur

Eksileri:

  • Tembel kalıpların ve değiştiricilerin sözdizimini bilmek gerekir