PHP中“空白”Unicode字符的字符串比较

时间:2015-12-14 16:34:36

标签: php unicode

我正在尝试检测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 mb_strlen()的结果也相同。

ctype_print()这样的函数不起作用,因为常规字符串可以包含不可打印的字符。

那么,有没有办法检测Unicode字符串是否会显示可打印的字符?

2 个答案:

答案 0 :(得分:1)

PHP regexp guide for unicode开始工作,我假设您要保留所有字母(L),标记(M),数字(N),标点符号(P),符号(S)和空格(Z)以及转储其他一切(如控制字符)。因此,正则表达式为:

$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;
 }
}

但我不喜欢迭代字符串并比较每个字符...如果你找到更好的方法,请告诉我。

答案 1 :(得分:0)

这个正则表达式怎么样?

<?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?"); // 1