PHP如何检查另一个字符串中是否存在utf-8字符串?

时间:2011-09-09 02:10:18

标签: php encoding utf-8

我真的为了解决这个问题而奋斗了一夜......但是:(

在表单中,用户输入一个单词,我需要检查他的输入是否包含预设的字符表中的字符:

abggwdḍefkkwhḤƐxqijlmnurṚɣsṢctṬwyzẒ

到目前为止,我使用的是在php.net中找到的代码:

$temp_s = mb_convert_encoding($post['word'],'UTF-16','UTF-8');
$temp_a = str_split($temp_s,4);
$temp_a_len = count($temp_a);

for($i=0; $i<$temp_a_len; $i++){
    $temp_a[$i] = mb_convert_encoding($temp_a[$i],'UTF-8','UTF-16');

    $pos = stripos( mb_strtolower($allowed),  mb_strtolower($temp_a[$i]) );
    if($pos === false){
        echo '- '. mb_strtolower($temp_a[$i]) .' -is not allowed in '.mb_strtolower($allowed);
        return false;
    } 
}

我做错了什么?因为如果我提交它输出的字符

- ḍ -is not allowed in abggwdḌefkkwhḤƐxqijlmnurṚɣsṢctṬwyzẒ

UPDATE 另一件事是如何允许$ allowed字符列表的大写或小写版本?

3 个答案:

答案 0 :(得分:2)

简单如下:

$unwanted = 'abggwdḍefkkwhḤƐxqijlmnurṚɣsṢctṬwyzẒ';
$badText  = 'Foo baṚ Baz';
$goodText = '345235';

if (preg_match_all("/[$unwanted]/u", $badText, $matches)) {
    echo "Bad text is bad, invalid characters: " . join(', ', $matches[0]) . PHP_EOL;
}

if (preg_match_all("/[$unwanted]/u", $goodText, $matches)) {
    echo "Good text is bad, invalid characters: " . join(', ', $matches[0]) . PHP_EOL;
}

请注意,您的源代码需要以UTF-8保存,输入也必须是UTF-8。

我真的质疑使用UTF-8黑名单,因为有数十万个代码点。将这些部分列入黑名单似乎是一场毫无用处的艰苦战斗。如果你不允许“Ṛ”,为什么你会接受“Ŗ”或任何其他类似“R”字符的变体。抓住它们都是徒劳的。考虑实现白名单。 (也就是说,如果我理解你要做什么的话。这不是很清楚。)

请注意,字符可能是decomposed,这意味着它们与您的表达式不匹配。例如,ü可以是字符ü(U + 00FC)或ü(U + 0075 U + 0308,即u后跟合并{{1} }})。您应该字符标准化为NFC(Canonical Decomposition后跟Canonical Composition),这意味着任何形式的¨都将标准化为U + 00FC。在PHP中,您可以使用:

ü

默认情况下,默认情况下并未安装Normalizer class

答案 1 :(得分:1)

我的日食没有问题

$allowed = 'ḍabggwdefkkwhḤƐxqijlmnurṚɣsṢctṬwyzẒ';
$temp_s = mb_convert_encoding('ḍ','UTF-16','UTF-8');
$temp_a = str_split($temp_s,4);
$temp_a_len = count($temp_a);

for($i=0; $i<$temp_a_len; $i++){
$temp_a[$i] = mb_convert_encoding($temp_a[$i],'UTF-8','UTF-16');

$pos = stripos( mb_strtolower($allowed),  mb_strtolower($temp_a[$i]) );
if($pos === false){
    echo '- '. mb_strtolower($temp_a[$i]) .' -is not allowed in '.mb_strtolower($allowed);

} 
}

答案 2 :(得分:1)

您发布的代码实际上似乎没有给我任何错误,但这是一个较短的版本。也许看看这是否符合你的要求。

$input = 'ḍwhat';

$allowed = mb_strtolower('ḍabggwdefkkwhḤƐxqijlmnurṚɣsṢctṬwyzẒ');

foreach (preg_split('//u', $input) as $c) {
  if (mb_strlen($c) !== 0 && mb_strpos($allowed, mb_strtolower($c)) === FALSE) {
    echo '-' . $c . '- is not allowded in ' . $allowed;
    return false;
  }
}

我唯一要说的是使用str_split($temp_s,2);来尝试原始代码,因为4并不总是有效,而更多的UTF-16东西将是2个字节。两者都可能会破裂。