2011-05-12 16 views
7

nasıl aç değil - preg_match_all('/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+"/ui', $outStr, $matches);regexp nasıl tırnak açmayın?

+1

Genel terimin 'tembel' olduğuna inanıyorum –

+1

@josh: Aslında, bu "açgözlü". –

+3

Aslında, * açgözlü * ve * tembel * terimleri, bazen gerçekte olup bitenleri maskeleyebilen daha uzun ve daha teknik terimler, kısayollar için yalnızca kısa yollardır. Daha teknik terimler, nicelleştiricilerin * maksimal *, * minimal * veya * sahiplenici * ile eşleşebilmeleridir, burada * *, '+', '?' Ve '{n, m}' ** maksimal settir * *; '*?', '+?', '' ve '{n, m}?', ** minimal kümesidir **; ve '* +', '++' ve '{n, m} +', sahip olma umuduyla **. Artı + 'tamlık için', ama yaptıklarını değiştirmez: düşün. – tchrist

cevap

11

En açlık yerine en kısa eşleşmeyi bulabileceğiniz gibi, açgözlülük demek istiyor musunuz? *, + ve ? niceleyicileri varsayılan olarak açgözlüdür ve mümkün olduğunca eşleşecektir. Onları açgözlü hale getirmek için bir soru işareti ekleyin.

preg_match_all('/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+?"/ui', $outStr, $matches); 

Açgözlü eşleme:

"foo" and "bar" 
^^^^^^^^^^^^^^^ 

Sigara hırslı eşleme:

"foo" and "bar" 
^^^^^ 
+0

Yeap, belirlemeye çalıştığım için? "Evet, ama işe yaramadı. –

3

bakınız: http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

U (PCRE_UNGREEDY)

Bu modifiye edicinin "açgözlülüğü", yani 'un varsayılan olarak açgözlü olmadıklarını, ise açgözlü olduklarını, sonra da? , Perl ile uyumlu değildir. da desen içinde bir (? U) değiştirici ayarı ile veya bir niceleyicinin (örn. *?) Arkasında bir işaretiyle ayarlanabilir. ASCII olmayan bunu apaçık, \x{⋯} kullanmıyor durumda kullandığınız kişileri göstermek için

/"[\pL\p{Nd}а-яА-ЯёЁ -_.+]+"/ui 

:

+2

Oops! PHP ve Java" (? U) "etiketini farklı şekilde kullanır. PHP'de" PCRE_UNGREEDY "regex derleme bayrağı açılır, ancak JDK7'de açılır. 'UNICODE_CHARACTER_CLASS' regex karakter sınıflarını [Unicode regex'leri] 'ne (http://www.unicode.org/reports/tr18/#Compatibility_Properties) uygun hale getirmek için bayrağı derler; bu, PHP'nin zaten varsayılan olarak yaptığı bir şeydir (inanıyorum!), Perl zaten zaten var. Hm, * pcrepattern * manpage okuma beni hafifçe şüpheli bırakır.Görünen, yukarıda belirtilen RL1.2 ne tam olarak değil, sadece [[pL \ pN]] gibi görünüyor. ASCII'den daha iyi – tchrist

+5

genellikle ne yaptığınızı bilmedikçe U kullanmak için (niceleyici davranışını ters çevirin) kötü bir fikirdir. Çok daha açık ve her birini ayrı ayrı kullanarak çevirmek için daha fazla kontrol sağlar? –

+0

@ Crayon: Anlaşıldı – tchrist

2

ou gönderdiğim

/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+"/ui 

eşdeğerdir önerdi Bu durumdan kaçınıyor:

/"[\pL\p{Nd}\x{430}-\x{44F}\x{410}-\x{42F}\x{451}\x{401} -_.+]+"/ui 
Ve adlandırılmış karakterleri kullanarak bir

:

/"[\pL\p{Nd}\N{CYRILLIC SMALL LETTER A}-\N{CYRILLIC SMALL LETTER YA}\N{CYRILLIC CAPITAL LETTER A}-\N{CYRILLIC CAPITAL LETTER YA}\N{CYRILLIC SMALL LETTER IO}\N{CYRILLIC CAPITAL LETTER IO} -_.+]+"/ui 

BTW, bu ilk, uniquote script yoluyla çalışan uniquote -v kullanılarak uniquote -x ve ikinci kullanılarak üretilmektedir.

Ve evet, PHP'nin henüz adlandırılmış karakterleri desteklemediğini veya en azından bunun hakkında konuşmayı kolaylaştırdığını biliyoruz. O bütün harfler, bu yüzden numaralandırma neden göremiyorum olamaz bunu düşünmek şimdi

U+0041 ‹A› \N{LATIN CAPITAL LETTER A} 
U+0061 ‹a› \N{LATIN SMALL LETTER A} 
U+00CB ‹Ë› \N{LATIN CAPITAL LETTER E WITH DIAERESIS} 
U+00EB ‹ë› \N{LATIN SMALL LETTER E WITH DIAERESIS} 

Ve:

U+0410 ‹А› \N{CYRILLIC CAPITAL LETTER A} 
U+0430 ‹а› \N{CYRILLIC SMALL LETTER A} 
U+0401 ‹Ё› \N{CYRILLIC CAPITAL LETTER IO} 
U+0451 ‹ё› \N{CYRILLIC SMALL LETTER IO} 
için

: Ayrıca, emin onlar benzerlere karıştırmayın yapar Kiril listesi. Bu , tüm Kiril harfleri istemez, bunun yerine sadece belirli bir set mi? Aksi takdirde ben tıpkı olacaktır:

/"[\pL\p{Nd} -_.+]+"/ui 

Hangi noktada bunu /i merak ediyorlar.maksimum karşılık gelen asgari sürümü, +? için + miktarının, çalışacak takas,

/"[\pL\p{Nd} -_.+]+"/u 

bahsedildiği gibi: Ben onun amacının ne göremiyorum, bu yüzden sadece yazardı

/"[\pL\p{Nd} -_.+]+?"/u 

Ancak, [ -_] aralığından, yani \p{SPACE}-\p{LOW LINE}'dan endişe duyuyorum. Çok tuhaf bir alan buluyorum. Bu, herhangi bir şey için sermaye ASCII harflerini tekrar eklemiş olduğunuz anlamına gelir.

% unichars -g '\p{ASCII}' '[\pS\pP]' 'ord() < ord(" ") || ord() > ord("_")' 
` U+0060 GC=Sk GRAVE ACCENT 
{ U+007B GC=Ps LEFT CURLY BRACKET 
| U+007C GC=Sm VERTICAL LINE 
} U+007D GC=Pe RIGHT CURLY BRACKET 
~ U+007E GC=Sm TILDE 

(Yani çıkış durumunda Merak ediyorsanız, unichars script değil.)

garip keyfi görünmektedir: Başka için, bazı semboller ve noktalama karakterleri ihmal ettik. Yani bu senin için yeterli olmayabilir olup olmadığını merak ediyorum:

/"[\pL\p{Nd}\s\pS\pP]+?"/u 

Şimdi düşünüyorum da, bu iki diğer sorunlara neden olabilir: O NFC şeklindedir varsayar

U+0401 ‹Ё› \N{CYRILLIC CAPITAL LETTER IO} 
U+0451 ‹ё› \N{CYRILLIC SMALL LETTER IO} 

(bir kanonik ayrışmanın kanonik bileşimi ile oluşturulur). Eğer NFC forma normalize edilmemiş verilerle ilgileniyor bir şans olsaydı, o zaman

NFD("\N{CYRILLIC CAPITAL LETTER IO}") => "\N{CYRILLIC SMALL LETTER IE}\N{COMBINING DIAERESIS}" 
NFD("\N{CYRILLIC SMALL LETTER IO}") => "\N{CYRILLIC CAPITAL LETTER IE}\N{COMBINING DIAERESIS}" 

hesaba olurdu Ve şimdi olmayan mektuplar var!

% uniprops "COMBINING DIAERESIS" 
U+0308 ‹◌̈› \N{COMBINING DIAERESIS} 
    \w \pM \p{Mn} 
    All Any Assigned InCombiningDiacriticalMarks Case_Ignorable CI Combining_Diacritical_Marks Dia Diacritic M Mn Gr_Ext Grapheme_Extend Graph GrExt ID_Continue IDC Inherited Zinh Mark Nonspacing_Mark Print Qaai Word XID_Continue XIDC 

Böylece belki aslında isteyeyim: Eğer Latin veya Kiril alfabeleri (ve, diyelim ki, Yunan veya Katakana gelmektedir yalnızca karakterleri içeren şekilde dize kısıtlamak istiyorsa

/"[\pL\pM\p{Nd}\s\pS\pP]+?"/u 

Ayrıca rakam ve çeşitli puntuation ve sembolleri almak Common gerektiğini hariç

/"(?:(?=[\p{Latin}\p{Cyrillic}])[\pL\pM\p{Nd}\s\pS\pP])+?"/u 

ve:), o zaman bu yönde bir lookahead eklersiniz , harflerinizi izleyen işaretleri birleştirmek için Inherited'a ihtiyacınız var.Yani bu bize getirir:

/"(?:(?!")(?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}])[\pL\pM\p{Nd}\s\pS\pP])+"/u 

yolu /x modunda çalışacak şekilde değil karmaşık oluyor:

şimdi çift tırnak arasında bir asgari maçı etkilemek için başka bir yol önerir

/"(?:(?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}])[\pL\pM\p{Nd}\s\pS\pP])+?"/u 

o Perl olsaydı

/ 
    "    # literal double quote 
    (?: 
    ### This group specifies a single char with 
    ### three separate constraints: 

     # Constraint 1: next char must NOT be a double quote 
     (?!") 

     # Constraint 2: next char must be from one of these four scripts 
     (?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}]) 

     # Constraint 3: match one of either Letter, Mark, Decimal Number, 
     #    whitespace, Symbol, or Punctuation: 
     [\pL\pM\p{Nd}\s\pS\pP] 

    )  # end constraint group 
    +  # repeat entire group 1 or more times 
    "  # and finally match another double-quote 
/ux 

, ben m{⋯}xu

01 ile o yazardı

Ama PHP'de bunun gibi eşlenmiş, parantez sınırlayıcıları yapıp yapamayacağınızı bilmiyorum.

Bu yardımcı olur umarız!