我正在尝试检测Unicode字符串是否可打印。
例如,我有一个用户,他将自己的名字设置为%EF%B8%8F -即variation selector-16 (U+FE0F)
我希望能够做一些像这样的事情
if ($screen_name == null || $screen_name == NotPrintable )
{
...Show an error...
} else {
...Proceed as normal...
}有没有办法检测Unicode字符串是否可打印?
用户名可以是任何有效的Unicode序列(英语、中文、阿拉伯语等)。
一些previous answers建议使用复杂的正则表达式,这些正则表达式看起来只适用于很小范围的字符。
我试着数了一下绳子的长度,但还是不行-
`$odd = urldecode("%EF%B8%8F"); print strlen($odd); 3` Same result for `mb_strlen()` as well.像ctype_print()这样的函数将无法工作,因为常规字符串可能包含不可打印的字符。
那么,有没有办法检测Unicode字符串是否会显示可打印字符呢?
发布于 2015-12-15 04:19:55
从PHP regexp guide for unicode开始,我假设您希望保留所有字母(L)、标记(M)、数字(N)、标点符号(P)、符号(S)和空格(Z),并转储其他所有内容(例如控制字符)。因此,下面的regexp:
$out=preg_replace('/[^\pL|\pM|\pN|\pP|\pS|\pZ]/u','',$in);看起来很管用。
编辑
好吧,这不适用于所提供的
$in=urldecode('%EF%B8%8F');示例(解码为Unicode代码点U+FE0F / ️。下面的代码可以处理它:
$len=mb_strlen($in);
$out='';
$disallowedTypes=[IntlChar::CHAR_CATEGORY_NON_SPACING_MARK];
for ($i=0;$i<$len;$i++) {
$char=mb_substr($in,$i,1);
$type=IntlChar::charType($char);
if (false===in_array($type,$disallowedTypes)) {
$out.=$char;
//print 'Adding ord '.dechex(IntlChar::ord($char)).' which is '.IntlChar::charType($char).PHP_EOL;
}
}但是我不喜欢遍历一个字符串并比较每个字符...如果你找到更好的方法,请告诉我。
发布于 2015-12-15 00:57:56
这个正则表达式怎么样?
<?php
define("CTYPE_PRINT_UNICODE_PATTERN", "~^[\pL\pN\s\"\~". preg_quote("!#$%&'()*+,-./:;<=>?@[\]^_`{|}´") ."]+$~u");
function ctype_print_unicode($input) {
return preg_match(CTYPE_PRINT_UNICODE_PATTERN, $input);
}
print ctype_print_unicode("3 muços?"); // 1https://stackoverflow.com/questions/34272088
复制相似问题