【问题标题】:How do I detect non-ASCII characters in a string?如何检测字符串中的非 ASCII 字符?
【发布时间】:2011-06-27 19:09:31
【问题描述】:

如果我有一个 PHP 字符串,我如何以一种有效的方式确定它是否包含至少一个非 ASCII 字符?非 ASCII 字符是指不属于此表的任何字符,http://www.asciitable.com/,位置 32 - 126(含)。

所以它不仅必须是 ASCII 表的一部分,而且还必须是可打印的。我想检测一个字符串,其中至少包含一个不符合这些规范的字符(不可打印的 ASCII 或完全不同的字符,例如不属于该表的 Unicode 字符。

【问题讨论】:

  • 所以你的意思不是Unicode,而是非US-ASCII?如果您正在寻找有效的东西,我认为这是值得指定的。
  • 你能对字符串做出任何安全的假设吗,比如编码?
  • 所有 ASCII 字符都是 也是 UTF-8 字符)。
  • 添加了说明。抱歉之前的歧义。

标签: php string


【解决方案1】:

我发现检测是否有任何字符不在列表中更有用

if(preg_match('/[^\x20-\x7e]/', $string))

【讨论】:

  • 记住 0x7F 是删除字符,所以它需要是 '/[^\x20-\x7e]/' 因为 0x7e 是 ~,所以这在技术上并不准确。
  • 这个答案很好,但是你可以在这篇帖子stackoverflow.com/questions/4147646/…中找到更多的解决方案
  • @wheresrhys 我认为您的 sn-ps 测试字符串中的所有字符是否都是 ascii,对于任何字符代码都应该是 /[^\x20-\x7f]/.test(theString)
  • @Karolis,我允许自己编辑您的答案:正如@simontemplar 6 年前在评论中正确指出的那样,7F (DEL) 不是可打印的 ASCII 字符。此外,OP 明确要求“32-126 inclusive”,翻译为20-7E。这个问题已经看了几千次了,你的回答是公认的,不要误导人!
【解决方案2】:

您可以使用mb_detect_encoding 并检查 ASCII:

mb_detect_encoding($str, 'ASCII', true)

如果$str 包含至少一个非ASCI 字符(字节值> 0x7F),这将返回false

【讨论】:

【解决方案3】:

【讨论】:

    【解决方案4】:

    如果所有字符都落在 ASCII 范围 32-126 (PHP unit test) 内,则函数 ctype_print 返回 true。

    【讨论】:

    • php -r 'echo ctype_print("\xa0");' 打印出1 所以这个函数有问题。
    • @forthrin:我无法确认。对我来说,php -r 'var_dump(ctype_print("\xa0"));' 返回 false(使用 PHP 7.0.10)。
    • 我也在 PHP 7.0.10 上,Homebrew 版本 (OS X)。会不会是终端、语言环境、php.ini 或其他环境因素造成的差异?
    • 对我也不起作用,Windows 上的 PHP 7.0.5 - 不知道为什么。它似乎不再起作用了。我们可能应该打开一个错误报告?
    【解决方案5】:

    我对建议的函数进行了基准测试,因为我需要对较短(最多 1000 个字符)字符串的批处理进行检查。我测试了 30 个不同字符串的 10k 次迭代(空、短、长、ascii、重音符号、日语、表情符号、非 ascii 开始、非 ascii 结束等)。以下是粗略的结果:

    mb_check_encoding:平均 95 毫秒。随着字符串变长 (1MB+),性能下降的速度比 preg_match 和 ctype 快。

    mb_check_encoding($input, 'ASCII');
    

    preg_match:平均 85 毫秒。对于 1MB+ 的字符串来说速度相当快(遍历字符串,如果字符串的前面有非 ascii 字符,速度会更快)。

    !preg_match('/[\\x80-\\xff]/', $input);
    

    ctype_print:平均 83 毫秒。对于 1MB+ 的字符串来说速度相当快(遍历字符串,如果字符串早期有非 ascii 字符,速度会更快)。 请注意,这并不是真正的 ascii 检查

    ctype_print($input);
    

    while/ord:平均 500 毫秒。我仍在等待 1MB+ 字符串测试完成。

    function is_ascii($input) {
        $num = 0;
        while( isset( $string[$num] ) ) {
            if( ord( $string[$num] ) & 0x80 ) {
                return false;
            }
            $num++;
        }
        return true;
    }
    

    【讨论】:

      【解决方案6】:

      你可以使用:

      mb_detect_encoding

      但它可能不会像您希望的那样精确。

      【讨论】:

        【解决方案7】:

        试试:(Source)

        function is_ascii( $string = '' ) {
            return ( bool ) ! preg_match( '/[\\x80-\\xff]+/' , $string );
        }
        

        尽管上述所有答案都是正确的,但根据输入的不同,这些解决方案可能会给出错误的答案。请参阅this ASCII validation post 的最后一节。

        【讨论】:

          【解决方案8】:

          我建议你查看 PHP 手册中的 utf8_encode 或 utf8_decode:

          http://www.php.net/manual/en/function.utf8-encode.php

          查看下面的示例,因为如果没有找到您正在寻找的东西,它可能会引导您走向正确的方向。

          【讨论】:

            【解决方案9】:

            如果你不想在javascript中处理Regex,你可以这样做

            detectUf8 : function(s) {
              var utf8=s.split('').filter(function(C) {
                return C.charCodeAt(0)>127;
              })
              return (utf8.join('').length>0);
            },
            

            【讨论】:

            • 这个问题是关于 PHP 而不是 JavaScript。
            猜你喜欢
            • 2016-04-09
            • 2013-05-27
            • 1970-01-01
            • 2011-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-25
            • 1970-01-01
            • 2015-07-01
            相关资源
            最近更新 更多