我有这个网页,用户可以在其中添加表情符号。我想限制每条评论的表情符号数量。 “系统”有效,但我对正则表达式部分有一些问题。 我在配置文件中定义了我的表情符号,如下所示:
$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
)
);
然后当我验证评论时(看看有多少表情符号),我循环通过这个数组并将微笑与评论的内容相匹配。正则表达式使用如下:
foreach ( $this->config['smilies'] as $smilie => $smilieImage )
{
$matches = Array ();
Preg_Match_All ( '/' . Preg_Quote ( $smilie ) . '/i', $Content, $matches );
$numOfFoundSmilies += Count ( $matches[0] );
}
问题是如果我在评论中输入“s:10”,上面的代码会找到两个匹配:“s:10”和“s:1”。我对正则表达式的了解非常差,我无法弄明白这一点。
答案 0 :(得分:4)
对于每个微笑代码,您的代码会计算代码在帖子中显示的次数,因此:10'计为's:10'和's:1'。
解决方案是一次性查找所有微笑代码,以便帖子的每一部分仅计入一个微笑代码。这可以通过将所有代码组合到单个正则表达式中来完成。
$codes = array_keys($smilie);
$escCodes = array_map('preg_quote', $codes);
$regex = '/'.implode('|',$escCodes).'/i';
preg_match_all($regex, $Content, $matches);
$found = count($matches);
答案 1 :(得分:3)
默认情况下,正则表达式为greedy(至少是PCRE)。通常你可以绕过这个:
/a+/ # selects the whiole string from "aaaaaaa"
/a+?/ # selects only "a"
在你的情况下,这没有多大帮助,因为你不能只是在某个地方扔一个问号。唯一的可能是重新排序您的搜索数组,并立即替换找到的地点。搜索s:10
的优先和s:1
的秒,并使用preg_replace()代替匹配。这样,第二个就不再找到第一个了。
另一种可能性:将您的搜索数组分成两部分。如果你知道,那个总是有结构的''加数字,你可以在第二个循环中使用你的正则表达式
Preg_Match_All ( '/' . Preg_Quote ( $smilie ) . '(?![0-9])/i', $Content, $matches );
(?![0-9])
一个look ahead expression正在寻找非 -digit。
还有第三个:如果您仅在某些地方允许(==转换)表情符号,则可以使用此功能:
Preg_Match_All ( '/\b' . Preg_Quote ( $smilie ) . '\b/i', $Content, $matches );
\b
是一个“单词边界”,通常不是 - (字母,数字,下划线)。显然,缺点是,并非所有的表情符号(如“abc ;-) xyz”都会被找到。
答案 2 :(得分:1)
我想这个代码比正则表达式更快
$replaced = str_replace(array_keys($config['Smilies']),
array_values($config['Smilies']),
$message, $count);
这不会解决s:1
和s:10
的问题,所以我建议为此使用更明确的分隔符/边界表示法,例如: :s10:
代替s:10
。那就不再是问题了。
另外,我建议不要使用数字标识符。用户可能会发现记住它们很乏味。为什么不使用易于记忆的标签,例如:heart:
或:lol:
?
答案 3 :(得分:0)
您可以将正则表达式更改为使用word boundaries或\ s(空白)进行匹配,因此s:1
变为\bs:1\b
或\ss:1\s
。请注意,第二种方法s:1.
将不会匹配,并且两个版本都不匹配This is my funny texts:1
。
答案 4 :(得分:0)
将“s:1”更改为“s:1 [^ 0-9]” - 匹配任何“s:1”后面没有其他数字。