如何检测字符串中的非 ASCII 字符?
Posted
技术标签:
【中文标题】如何检测字符串中的非 ASCII 字符?【英文标题】:How do I detect non-ASCII characters in a string? 【发布时间】:2011-06-27 19:09:31 【问题描述】:如果我有一个 php 字符串,我如何以一种有效的方式确定它是否包含至少一个非 ASCII 字符?非 ASCII 字符是指不属于此表的任何字符,http://www.asciitable.com/,位置 32 - 126(含)。
所以它不仅必须是 ASCII 表的一部分,而且还必须是可打印的。我想检测一个字符串,其中至少包含一个不符合这些规范的字符(不可打印的 ASCII 或完全不同的字符,例如不属于该表的 Unicode 字符。
【问题讨论】:
所以你的意思不是Unicode,而是非US-ASCII
?如果您正在寻找有效的东西,我认为这是值得指定的。
你能对字符串做出任何安全的假设吗,比如编码?
所有 ASCII 字符都是 也是 UTF-8 字符)。
添加了说明。抱歉之前的歧义。
类似于***.com/questions/4147646/…
【参考方案1】:
我发现检测是否有任何字符不在列表中更有用
if(preg_match('/[^\x20-\x7e]/', $string))
【讨论】:
记住 0x7F 是删除字符,所以它需要是 '/[^\x20-\x7e]/' 因为 0x7e 是 ~,所以这在技术上并不准确。 这个答案很好,但是你可以在这篇帖子***.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。
【讨论】:
mb_check_encoding
更合适:mb_check_encoding($str, 'ASCII')
【参考方案3】:
试试 (mb_detect_encoding)
【讨论】:
【参考方案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。以上是关于如何检测字符串中的非 ASCII 字符?的主要内容,如果未能解决你的问题,请参考以下文章
处理 textField:shouldChangeCharactersInRange:replacementString: 中的非 ascii 字符
SyntaxError:函数返回“£”时文件中的非 ASCII 字符“\xa3”