我正在尝试在我的php代码中检测表情符号,并阻止用户输入它。
我的代码是:
if(preg_match('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', $value) > 0)
{
//warning...
}
但不适用于所有表情符号。有什么想法吗?
答案 0 :(得分:10)
if(preg_match('/\xEE[\x80-\xBF][\x80-\xBF]|\xEF[\x81-\x83][\x80-\xBF]/', $value)
您确实希望在字符级别匹配Unicode,而不是尝试跟踪UTF-8字节序列。使用u
修饰符以字符为基础处理您的UTF-8字符串。
表情符号在块U + 1F300-U + 1F5FF中编码。但是:
来自日本航空公司的许多角色' 'emoji'集实际上映射到现有的Unicode符号,例如卡套装,十二生肖和一些箭头。你现在把这些符号算作“表情符号”吗?
仍有系统不使用新标准化的Unicode表情符号代码点,而是使用私有使用区域中的ad-hoc范围。每个运营商都有自己的编码。 iOS 4使用了Softbank集。 More info.您可能希望阻止整个私人使用区。
例如:
function unichr($i) {
return iconv('UCS-4LE', 'UTF-8', pack('V', $i));
}
if (preg_match('/['.
unichr(0x1F300).'-'.unichr(0x1F5FF).
unichr(0xE000).'-'.unichr(0xF8FF).
']/u'), $value) {
...
}
答案 1 :(得分:2)
来自维基百科:
从Unicode 6.0开始设置的核心表情符号由722个字符组成 其中114个字符映射到一个或多个字符的序列 6.0之前的Unicode标准,其余608个字符映射到 Unicode 6.0中引入的一个或多个字符的序列。[4] 没有专门为表情符号预留块 - 新符号 被编码在七个不同的块(一些新创建的)中,并在那里 存在一个名为EmojiSources.txt的Unicode数据文件,其中包含 与日本供应商的遗留字符集之间的映射。
这是mapping file。文件中有722行,每行代表722个表情符号中的一个。
这似乎不是一件容易的事,因为没有为表情符号预留特定的块。您需要调整正则表达式以涵盖所有表情符号unicodes。
您可以像这样匹配单个unicode:
\x{1F30F}
1F30F是地球表情符号的unicode。
对不起,我没有给你一个完整的答案,但这应该让你朝着正确的方向前进。
答案 2 :(得分:1)
正确的答案是检测Miscellaneous_Symbols_And_Pictographs
块中指定代码点的位置。在Perl中,您将使用
/\p{Assigned}/ && \p{block=Miscellaneous_Symbols_And_Pictographs}/
或只是
/\P{Cn}/ && /\p{Miscellaneous_Symbols_And_Pictographs}/
你应该将它们与
组合成一个模式/(?=\p{Assigned})\p{Miscellaneous_Symbols_And_Pictographs}/
我不记得PHP使用的PCRE库是否允许您访问必需的Unicode字符属性。我的回忆是,在那个特定区域它很弱。我认为你只有Unicode脚本属性和一般类别。叹息。
有时你只需要使用真实的东西。
由于缺乏合适的Unicode支持,您可能必须自己枚举该块:
/(?=\P{Cn})[\x{1F300}-\x{1F5FF}]/
看起来像是一场维护噩梦,充满了神奇的数字。
答案 3 :(得分:0)
这是我的解决方案,它是一个更简单的(感谢 php7)版本的 bobince's 答案。
<?php
if (preg_match("/[\u{1f300}-\u{1f5ff}\u{e000}-\u{f8ff}]/u", $text)) {
// echo "? oh no. Emojis not allowed!";
}
EDIT 根据 bobnice 的回答的建议,此正则表达式排除了实际的表情符号范围 (1f300
- 1f5ff
) 和 bobnice 提出的您可能感兴趣的其他范围在阻塞中。
EDIT 2 要明确:这种更简单的格式在 PHP 7.0+ 中是可能的。如果您仍在使用(现在不受支持)版本的 PHP,则需要使用原始答案。
答案 4 :(得分:-2)
这就是我今天想出来的。对于这个问题,它可能不是一个好的解决方案,但至少它可以工作;)
if(iconv('Windows-1250', 'UTF-8', iconv('UTF-8', 'Windows-1250', $value)) != $value)