Literal dize Maç

5 Cevap php

I have this web page where users can add smilies to their comments. And I want to limit the number of smilies per comment. The "system" works but I have some problems with the regex part. I have my smilies defined in a config file like so:

$config['Smilies'] = Array (
    // irrelevant stuff
    'smilies' => Array (
    	':)' => 'smile.gif',
    	':(' => 'sad.gif',
    	// some more smilies
    	's:10' => 'worship.gif',
    	's:11' => 'zip.gif',
    	's:12' => 'heart.gif',
    	// some more smilies
    	's:1' => 'dry.gif',
    	's:2' => 'lol.gif',
    	's:3' => 'lollol.gif',
    	// some more smilies
    )
);

Ve sonra ben (orada kaç gülümsemeleri görmek için), ben döngü yalak bu diziyi Yorumu doğrulamak ve yorumun içeriği gülümseme maç ne zaman. Regex şöyle kullanılır:

foreach ( $this->config['smilies'] as $smilie => $smilieImage )
{
    $matches = Array ();
    Preg_Match_All ( '/' . Preg_Quote ( $smilie ) . '/i', $Content, $matches );

    $numOfFoundSmilies += Count ( $matches[0] );
}

The problem is o I "s: 10" girerseniz: "s: 10" ve "s: 1" yorumun içine, yukarıdaki kodu iki maç bulabilirsiniz. Düzenli ifadelerin bilgim çok kötü ve ben bunu çözemiyorum.

5 Cevap

Düzenli ifadeler greedy varsayılan (en azından PCREs) tarafından bulunmaktadır. Genellikle bu atlatmak olabilir:

/a+/ # selects the whiole string from "aaaaaaa"

/a+?/ # selects only "a"

Senin durumunda, bu sadece bir yerde bir soru işareti atmak değil çünkü, çok yardımcı olmuyor. Sadece olasılık re-order arama dizi ve anında replace bulunan yerlere etmektir. Ara first s:10 ve second s:1 için ve preg_replace() yerine eşleştirme kullanımı için. Bu şekilde, ikinci artık ilk bulmuyor.

Another possibility: ikiye arama dizi Böl. Eğer biliyorsanız, bir zaman yapısı 's:' olduğunu artı basamak, sizin gibi bu ikinci döngü içinde regexpi olabilir

Preg_Match_All ( '/' . Preg_Quote ( $smilie ) . '(?![0-9])/i', $Content, $matches );

ile (?![0-9]) bir look ahead expression herhangi bir non haneli arıyor.

Eğer sadece belirli yerlerde (==) dönüştürmek suratlar izin verirseniz And a third one:, bu kullanabilirsiniz:

Preg_Match_All ( '/\b' . Preg_Quote ( $smilie ) . '\b/i', $Content, $matches );

\b "word sınır", genellikle herhangi bir not-(harf, rakam, çizgi) 'dir. Dezavantajı ("abc ;-) xyz" gibi) tüm suratlar bulundu olacak değil, açıkçası.

Sizin kod sayımları, her gülümseme kodu için, kaç kez bu kod böylece 's: 10', yazı görünür: ve 's: 1' hem '10 s' olarak sayar.

Yazılan her parça tek bir gülümseme kod doğru sayar, böylece bir çözüm, bir kerede tüm gülümseme kodları için bakmak olacaktır. Bu, tek bir regex içine tüm kodları birleştirerek yapılabilir.

$codes = array_keys($smilie);
$escCodes = array_map('preg_quote', $codes);
$regex = '/'.implode('|',$escCodes).'/i';

preg_match_all($regex, $Content, $matches);

$found = count($matches);

Bu kodu bir Regex daha hızlı olmasını hayal ediyorum

$replaced = str_replace(array_keys($config['Smilies']), 
                        array_values($config['Smilies']),
                        $message, $count);

Bu s:1 ve s:10 olsa, ben bunun için daha net bir ayraç / sınır gösterimde, örneğin kullanmayı öneririm ile sorunları çözmek olmaz :s10: yerine s:10. Sonra artık bir sorun olmayacak.

Buna ek olarak, ben zaten bunun için sayısal tanımlayıcılar kullanmak için değil öneririm. Kullanıcı olasılıkla sıkıcı onları hatırlamak bulacaksınız. Neden etiketleri ezberlemek için kullanımı kolay değil, örneğin :heart: veya :lol:?

Öyle s:1 \bs:1\b veya \ss:1\s olur, word boundaries veya \ s (boşluk) eşleştirmek için kullanmak için regexen değişebilir. s:1. uyumlu olmayacak ikinci yöntem ile dikkat edin, ve her iki versiyon maç olmayacak This is my funny texts:1.

Değiştir "s: 1" "s: 1 [^ 0-9]" - herhangi eşleşir "s: 1" Başka sayısına göre takip değil.