Düzenli ifadeler php veya. Normal ifadeler (desenler)

  • 02.06.2019

) Size bir sayfanın kaynak kodunun belirli parçalarını bulmak için normal ifadelerin kullanımına bir örnek gösterdim. Şimdi bunları nasıl yazacağımızı kendimiz öğreneceğiz. Bu beceri, yazmanıza, gereksiz parçalardan metin temizlemenize, büyük hacimli metinlerde gerekli kısımları aramanıza vb. Yardımcı olacaktır.

Bu konu oldukça zor ama en önemli noktaları kısaca vurgulamaya çalışacağım. Bunu ne kadar yapabilirim bilmiyorum ama umarım ders faydalı olur.
Yani, başlangıç \u200b\u200bolarak, PHP'de normal ifadelerle çalışmak için birkaç işlev vardır, ancak çoğunlukla üç işlev kullanılır:

  • preg_replace - normal ifadeyle eşleşen metni arayın ve değiştirin;
  • preg_match - sadece normal arama;
  • preg_split - metni arayın ve bölün.

En azından önceki derslerde onları kullandık. Aksine, preg_match yerine preg_match_all vardı, ancak bu aslında aynı şeydir, sadece ikincisi ilk bulgudan sonra aramayı kesintiye uğratmaz. Yani, preg_match kullanırsak, tüm oluşumlarını değil, yalnızca ilkini bulacağız.

Hangi durumda hangi fonksiyonun kullanılacağına karar vermek oldukça basittir. Değiştirmemiz gerekiyor - sayfa kodunun gereksiz kısımlarını kaldırmamız gerektiğinde olduğu gibi değiştirmeyi kullanırız, hatırladın mı?

$ sayfa \u003d preg_replace ("/ ^] / i "," ", $ sayfa); $ sayfa \u003d preg_replace (" / ^] / i "," ", $ sayfa); $ sayfa \u003d str_replace (""," ", $ sayfa);

Fonksiyonun ilk parametresi, aradığımızı tanımlayan bir normal ifadedir. İkincisi, değiştirdiğimiz şeydir. Üçüncüsü - Baktığımız yer. Bu nedenle, burada $ page değişkenini aldık ve preg_replace işlevinin sonucunu ona atadık, burada tüm girdi türü \u003d onay kutularını ve ayrıca açma ve kapama etiketlerini aradık. Bunları "ile değiştirdiler, yani basitçe kaldırıldılar. Umarım burada her şey açıktır. Biraz sonra ifadenin (fonksiyonun ilk parametresi) analizine geçeceğiz.
Metnin geri kalanındaki tüm bağlantıları bulmak için kullanışlı olan preg_match_all kullanımının bir örneği de vardı. Daha sonra, ayrıştırdığımız anahtar kelimeleri içerdikleri için bağlantılara ihtiyacımız vardı. İşte olanlar:

Preg_match_all ("/ ]+?>(.*?)<\/a>/ uis ", $ sayfa, $ ok); için ($ j \u003d 0; $ j ". $ ok [$ j].""; }

İlk parametre, yine, doğal olarak "a" etiketi içinde bulunan tüm bağlantıları bulmak için normaldir (html işaretlemesine uygun değilseniz, okuyun). İkincisi, aramanın gerçekleştirileceği metni içeren bir değişkendir. Üçüncü parametre, sonucun yerleştirildiği bir değişkendir - $ ok. Bundan sonra, ihtiyacımız olan anahtarları elde etmek için sadece gerekli tüm $ ok öğelerinin üzerinden geçmek kalır. Ayrı olarak, çıktıda çok boyutlu bir dizi elde ettiğimiz söylenmelidir. Bu yüzden onu bu kadar karmaşık bir şekilde çıkarıyoruz: $ ok [$ j]. Dizinin yapısını görmek için aşağıdaki işlevi kullanın ve her şeyi anlayacaksınız.

Print_r ($ ok);

Görünüşe göre, işte kullandığımız işlevleri anladık. Şimdi geriye sadece bu yöntemlerin her birinin ilk parametresi olan bu çok düzenli ifadelerin nasıl yazılacağını öğrenmek kalıyor. En önemli şeye geçelim.

Düzenli nasıl yazılır

Öncelikle temel yapılara bir göz atalım. İfadelerin seçenekleri vardır. Bir harfle belirtilirler ve sonunda eğik çizgi ile yazılırlar.

Ek olarak, aşağıdaki meta karakterler desteklenir:

Metakarakterler de değiştiricilere sahip olabilir:

Pekala, şimdi son dersten müdavimlerimizin analizine geçebiliriz. Yukarıdaki tabletlere dayanarak elimizde ne olduğunu anlamaya çalışalım. İşte ifade:

/^] / i

İlk ve son eğik çizgiler "/", içlerinde normal bir ifade olduğunu gösterir. Aynı zamanda, sonuncudan sonra "i" koyarız, bu ilk tablodaki gibi bir seçenektir - büyük / küçük harfe duyarlı değildir. Eğik çizgilerin içinde normal çizginin kendisi var. Küçüktür işaretiyle ve bir girdi etiketiyle başlar ve bundan sonra ne gelirse gelsin, bir noktaya kadar, ki bu aranması gereken basit bir metindir. Ama noktanın kendisi ve ondan sonraki semboller - bu zaten daha ilginç. Bu durumda, yapı ". *?" herhangi bir karakter dizisi anlamına gelir. Yani, sadece metni ve verilen yapıyı birleştirirseniz, o zaman ilk oluşumdan sonra tüm metni sonuna kadar seçeceğiz. Durdurmak için, kapanış html etiketi "büyüktür" veya yeni satır karakteriyle karşılaşmanız gerekir. Bu tasarım bize şu fırsatı veriyor:

Köşeli parantez içindeki semboller mantıksal VEYA ile bağlantılıdır. Son, işaretten büyük VEYA satırın başlangıcıdır.
Bütün ifade bu, içinde başlangıç \u200b\u200bkoşulunu, orta ve bitiş koşullarını belirledik. Zor değil, değil mi? İşte netlik için bir örnek:

Her şeyi sağlamlaştırmak için bir tane daha parçalayalım. Bağlantılar için onları aradık:

/]+?>(.*?)<\/a>/ uis

İfadeyi okuyoruz. Yine, önce eğik çizgileri ve seçenekleri atın. Tanımlamadığım "u" haricinde "uis" bayrakları anlaşılabilir - bu, Unicode kodlama kullandığımızı gösterir. Geriye pek bir şey kalmadı. Başlangıç, açılan ve ardından sınıfa gelen "a" etiketidir

bu, daha fazla veya daha az DEĞİL (html etiketlerini açma ve kapatma), yani bu durumda herhangi bir karakter anlamına gelir. Sınıfa "+?" Eklenir, yani bu sınıf 1 veya daha fazla kez (ancak kesin olarak en az 1 kez) olacaktır. Ve sonra "a" etiketi için kapanış html etiketi gelir. Bağlantının içinde grup tarafından belirlenen metin var

Ne de olsa orada ne tür bir metin olacağını bilmiyoruz, bu yüzden böyle bir grup tanımlıyoruz. Ve sonunda, "a" kapanış etiketi:

Düz metin olarak algılanması için eğik çizgiden ters eğik çizgiyle kaçtığımızı lütfen unutmayın.

Fuh. Konu gerçekten oldukça karmaşık, pratik gerektiriyor. Belki de pek iyi bir şey yapmıyorum ve başka, daha doğru normal ifadeler oluşturmak mümkün, ancak ben de sizin kadar kendi kendime öğretiyorum, bu yüzden katı bir şekilde yargılamayın, bunun yerine seçeneklerinizi yorumlarda paylaşın. Ayrıca, net olmayan bir şey varsa, yorumlar ve bir iletişim sayfası hizmetinizdedir.

Normal ifadeler çok güçlü ancak anlaşılması zor bir dizi işleme aracıdır. Ana noktaları anlatacağım. Normal ifade bir dize modelidir. Bu kalıbı kullanarak, oluşum arayabilir, değiştirmeler yapabilir, kalıp eşleştirmesini kontrol edebilirsiniz.

Kalıp oluşturma kuralları

Şablonun sınırları belirli sembollerle gösterilmelidir, genellikle " / "ama kullanmayı tercih ederim" # "çünkü öne / ters eğik çizgilerin bolluğu gözlerinizi berbat gösterebilir ve" kafesler "genellikle başka hiçbir yerde kullanılmaz. Yani:" #RegularExpressionBody #"

Normal ifadenin içinde parantezler kullanılır - bunlar değiştirilebilen alt ifadelerdir, örneğin:

# ^ / katalog / (+) / (+) \\. html. * #

Bu ifade, bir dizedeki parametreleri almak içindir URL... Satırın başında özel bir karakter var " ^ "- bu bir satırın başlangıcı anlamına gelir. Sonra gelir" / katalog /"- özel karakter yoktur, bu yalnızca dizede yer alması gereken metindir. Sonra parantezlerle karşılaştılar, yani ilk alt ifadeye ulaştılar. Köşeli parantezler, bu yerde dizede bulunabilecek bir karakter kümesini belirtir . - "numaralandırma anlamına gelir. İşaret" \ "özel karakterlerden kaçar. Böylece, ilk alt ifadede Latin alfabesinin BÜYÜK ve küçük harfleri, 0'dan 9'a kadar sayılar, alt çizgi, kısa çizgi ve nokta olabilir. Kısa çizgi ve nokta özel karakterlerdir, ancak burada kaçarlar burada sadece semboller var. Köşeli parantezlerden sonra bir " + "- bu, önceki karakterin (ve köşeli parantez içinde bu karakter kümesine sahibiz) 1 veya daha fazla kez gidebileceği anlamına gelir. Sonra gelir" / "sadece bir karakter ve benzer bir ikinci alt ifade. Sonra gelir" \\ .html"bu metin anlamına gelir" .html". Ve sonra özel karakterler" .* "nokta, herhangi bir karakter anlamına gelir ve yıldız işareti, önceki karakterin herhangi bir miktarı anlamına gelir. Yani, sonra" .html"her şey gidebilir.

Miktar göstergesi, niceleyiciler

Yukarıda, önceki karakterlerin sayısını gösteren bu tür karakterleri zaten düşündük, örneğin: + ve * ... Miktarı belirtmek için tüm olasılıklar şunlardır:

Özel karakterler

Bazı karakter grupları için özel kısaltmalar vardır:

"Açgözlülük"

Normal ifade açgözlülüğü kavramına bir göz atalım. Örneğin, bir satır var:

#()#

Okuruz: alt ifade:

Her şey doğruysa alt ifade şunlarla eşleşir:

Ama aynı zamanda şunlara da uyuyor:

Onu alacağız çünkü normal ifadeler varsayılan olarak açgözlüdür. Açgözlülüğü " U", böyle:

#() #U

Değiştiriciler

Normal ifadenin ardından değiştiriciler gelebilir: " #TutRegularExpressionBody #TutModifiers"Değiştirici türleri:

ben Büyük / küçük harfe duyarsız modu açar, ör. büyük ve küçük harfler ifade açısından farklılık göstermez.
m Aranmakta olan metnin birden çok satır olarak değerlendirilmesi gerektiğini belirtir. Varsayılan olarak, normal ifade motoru, gerçekte ne olduğuna bakılmaksızın metni tek bir dize olarak ele alır. Buna göre, meta karakterler "^" ve "$" tüm metnin başlangıcını ve sonunu gösterir. Bu değiştirici belirtilirse, sırasıyla her metin satırının başına ve sonuna işaret edeceklerdir.
s Varsayılan meta karakter " . ", tanımında satır besleme karakteri içermiyor. Bu değiştiricinin belirtilmesi bu kısıtlamayı kaldırır.
U Normal ifadenin açgözlülüğünü ortadan kaldırır
sen Normal ifadelerin birlikte çalışmasını sağlar kiril'den UTF-8'eaksi takdirde düzgün çalışmaz.

normal ifadelerle çalışmak için php İşlevleri

preg_replace

Bul ve Değiştir:

Preg_replace (karışık $ şablon, karışık $ değiştirme, karışık $ konu [, int $ limit \u003d -1 [, int & $ say]]);

Her değer bir dize veya bir dizi olabilir. $ konu dizi - bir dizi döndürülür, aksi takdirde bir dizge

preg_split

Normal bir ifade kullanarak bir dizeyi böler:

Preg_split (string $ şablon, string $ konu [, int $ limit \u003d -1 [, int $ bayraklar \u003d 0]]);

Verilen dizenin bir dizi alt dizesini döndürür konukalıba uyacak şekilde parçalanmış desen.

Normal ifadeler, metinde bir alt dizeyi bulmaya yönelik özel kalıplardır. Onların yardımıyla, şu görevleri tek satırda çözebilirsiniz: "dizenin sayı içerip içermediğini kontrol edin", "metindeki tüm e-posta adreslerini bulun", "birkaç ardışık soru işaretini biriyle değiştirin".

Popüler bir programlama bilgeliğiyle başlayalım:

Bazı insanlar bir problemle karşılaştıklarında şöyle düşünürler: "Evet, zekiyim, bunu normal ifadelerle çözeceğim." Şimdi onların iki problemi var.

Örnek şablonlar

Birkaç basit örnekle başlayalım. Aşağıdaki resimdeki ilk ifade 3 harflik bir diziyi arar; burada ilk harf "k", ikincisi herhangi bir Rus harfi ve üçüncüsü büyük / küçük harfe duyarlı olmayan "t" (örneğin, "kedi" veya " CAT "bu kalıpla eşleşir). İkinci ifade metindeki saati 12:34 biçiminde arar.

Herhangi bir ifade, sınırlayıcı bir karakterle başlar. / Sembolü genellikle olduğu gibi kullanılır, ancak normal desenlerde özel bir amacı olmayan diğer sembolleri de kullanabilirsiniz, örneğin ~, # veya @. İfadede / göründüğünde alternatif sınırlayıcılar kullanılır. Ardından aradığımız dizenin kalıbı gelir, ardından ikinci bir sınırlayıcı gelir ve sonunda bir veya daha fazla bayrak harfi olabilir. Metin ararken ek seçenekler sağlarlar. İşte bazı bayrak örnekleri:

  • i - aramanın büyük / küçük harfe duyarlı olmaması gerektiğini söylüyor (varsayılan olarak büyük / küçük harfe duyarlı)
  • u - ifadenin ve aranan metnin yalnızca Latin harflerini değil utf-8 kodlamasını kullandığını söylüyor. Bu olmadan, Rusça (ve Latin olmayan diğer) karakterlerin aranması düzgün çalışmayabilir, bu nedenle her zaman kullanmalısınız.

Şablonun kendisi normal sembollerden ve özel yapılardan oluşur. Örneğin, normal çizgilerdeki "k" harfi kendisini temsil eder, ancak semboller "bu yerde 0'dan 5'e kadar herhangi bir sayı olabilir" anlamına gelir. İşte özel karakterlerin tam listesi (php kılavuzunda bunlar meta karakterler olarak adlandırılır) ve normal ifadedeki diğer tüm karakterler normaldir:

Aşağıda bu karakterlerin her birinin anlamını analiz edeceğiz (ve ayrıca "ё" harfinin neden ilk ifadede ayrı ayrı oluşturulduğunu açıklayacağız), ancak şimdilik normal ifadelerimizi metne uygulamaya çalışalım ve ne olacağını görelim. Php, girdi olarak normal bir desen, metin ve boş bir diziyi kabul eden özel bir preg_match ($ regexp, $ text, $ match) işlevine sahiptir. Metnin verilen kalıpla eşleşen bir alt dize içerip içermediğini kontrol eder ve değilse 0 veya varsa 1 döndürür. Ve aktarılan dizide, normal ifadeyle bulunan ilk eşleşme, dizin 0 olan öğeye yerleştirilir. Normal ifadeleri farklı dizelere uygulayan basit bir program yazalım:

Örnekle tanıştıktan sonra, normal ifadeleri daha ayrıntılı olarak inceleyeceğiz.

Normal ifadelerde parantezler

Farklı parantez türlerinin ne anlama geldiğini özetleyelim:

  • Küme parantezleri a (1,5) önceki karakterin tekrar sayısını belirtir - bu örnekte ifade, 1 ila 5 ardışık harf "a" arar
  • Köşeli parantezler "bu karakterlerden herhangi biri" anlamına gelir; bu durumda a, b, c, x, y, z harfleri veya 0'dan 5'e kadar bir sayı. veya * - normal bir karakteri temsil ederler. ^ Simgesi köşeli parantezlerin başındaysa, anlamı tersine çevrilir: "belirtilenler dışında herhangi bir karakter" - örneğin [^ a-c], "a, b veya c dışında herhangi bir karakter" anlamına gelir.
  • Parantezler, karakterleri ve ifadeleri gruplandırır. Örneğin, abc + ifadesinde artı işareti yalnızca c harfini ifade eder ve bu ifade abc, abcc, abccc gibi sözcükleri arar. Parantez a (bc) + koyarsanız, nicelik belirteci artı bc dizisine başvurur ve ifade abc, abcbc, abcbcbc kelimelerini arar.

Not: Köşeli parantez içindeki karakter aralıklarını belirtebilirsiniz, ancak Rusça ё harfinin alfabeden ayrı olduğunu ve "herhangi bir Rus harfi" yazmak için [a-yayo] yazmanız gerektiğini unutmayın.

Bexsles

Diğer normal ifade öğreticilerine baktıysanız, muhtemelen ters eğik çizginin her yerde farklı yazıldığını fark etmişsinizdir. Bir yere bir ters eğik çizgi yazarlar: \\ d, ancak burada örneklerde 2 kez tekrarlanır: \\\\ d. Neden?

Normal ifade dili, bir kez ters eğik çizgi yazmanızı gerektirir. Bununla birlikte, PHP'deki tek ve çift tırnaklı dizgelerde ters eğik çizginin özel bir anlamı da vardır: dizeler üzerine eğitim. Örneğin, $ x \u003d "\\ $" yazarsanız; o zaman PHP bunu özel bir kombinasyon olarak alır ve dizeye yalnızca $ karakterini ekler (ve düzenli ifade motoru ondan önceki ters eğik çizgiyi bilmez). \\ $ Dizisini bir dizeye eklemek için ters eğik çizgiyi ikiye katlamalı ve kodu $ x \u003d "\\\\ $" şeklinde yazmalıyız; ...

Bu nedenle, bazı durumlarda (bir karakter dizisinin PHP'de özel bir anlamı olduğu durumlarda) ters eğik çizgiyi ikiye katlamamız gerekir:

  • Düzenli ifadeye \\ $ yazmak için "\\\\ $" kodunu yazıyoruz
  • Normal ifadede \\\\ yazmak için, her ters eğik çizgiyi ikiye katlar ve "\\\\\\\\" yazarız
  • Normal ızgaraya bir ters eğik çizgi ve bir sayı (\\ 1) yazmak için ters eğik çizgiyi ikiye katlayın: "\\\\ 1"

Diğer durumlarda, bir veya iki ters eğik çizgi aynı sonucu verecektir: "\\\\ d" ve "\\ d" dizeye bir çift \\ d karakteri ekleyecektir - ilk durumda 2 ters eğik çizgi, ters eğik çizgi eklemek için bir dizidir, ikinci durumda özel bir sıra yoktur ve karakterler oldukları gibi eklenir. Dizeye hangi karakterlerin eklendiğini ve normal ifade motorunun gördüklerini echo ile kontrol edebilirsiniz: echo "\\ $"; ... Evet zor, ama ne yapabilirsin?

Düzenli olarak özel yapılar

  • \\ d herhangi bir rakam arar, \\ D - rakam hariç herhangi bir karakter
  • \\ w herhangi bir tek harf (herhangi bir alfabe), rakam veya alt çizgi _ ile eşleşir. \\ W harf, sayı ve alt çizgi dışındaki herhangi bir karakterle eşleşir.

Ayrıca, bir kelime sınırını belirtmek için uygun bir koşul vardır: \\ b. Bu yapı, bir tarafında harf / sayı / alt çizgi (\\ w) olan bir karakter olması gerektiği ve diğer tarafta olmadığı anlamına gelir. Örneğin, metinde "kedi" kelimesini bulmak istiyoruz. Normal ifadeyi / kedi / ui'yi yazarsak, bu harflerin sırasını her yerde bulur - örneğin "sığır" kelimesinin içinde. Bu açıkça istediğimiz şey değil. Normal kareye sınır koşulu eklersek: / \\ bcat \\ b / ui, o zaman artık sadece ayrı bir kelime olan "kedi" aranacaktır.

Manuel

  • PHP Normal İfade Söz Dizimi, Ayrıntılı Açıklama