PHP:如何删除string中的所有不可打印的字符?

我想我需要删除字符0-31和127,

有没有一个function或一段代码来有效地做到这一点。

7位ASCII码?

如果你的Tardis只是在1963年登陆,而你只想要7位可打印的ASCII字符,那么你可以从0-31和127-255中删除所有的东西:

$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string); 

它匹配范围0-31,127-255中的任何内容并将其删除。

8位扩展ASCII?

你掉进热水浴缸的时间机器,你又回到了八十年代。 如果你有一些8位的ASCII码,那么你可能想把字符保持在128-255之间。 一个简单的调整 – 只要find0-31和127

 $string = preg_replace('/[\x00-\x1F\x7F]/', '', $string); 

UTF-8?

啊,欢迎回到21世纪。 如果你有一个UTF-8编码的string,那么可以在正则expression式中使用/u 修饰符

 $string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string); 

这只是删除0-31和127.这在ASCII和UTF-8工作,因为两者共享相同的控制设置范围 (由mgutt下面)。 严格来说,这将工作没有/u修饰符。 但是,如果你想删除其他字符,它会使生活更轻松…

如果你正在处理Unicode, 可能会有很多非打印元素 ,但是让我们考虑一下: NO-BREAK SPACE(U + 00A0)

在UTF-8string中,这将被编码为0xC2A0 。 您可以查找并删除特定的序列,但使用/u修饰符后,您可以简单地将\xA0添加到字符类:

 $string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string); 

附录:str_replace呢?

preg_replace是非常高效的,但是如果你正在做这个操作很多,你可以build立一个你想删除的字符数组,并使用下面的mgutt指出的str_replace,例如

 //build an array we can re-use across several operations $badchar=array( // control characters chr(0), chr(1), chr(2), chr(3), chr(4), chr(5), chr(6), chr(7), chr(8), chr(9), chr(10), chr(11), chr(12), chr(13), chr(14), chr(15), chr(16), chr(17), chr(18), chr(19), chr(20), chr(21), chr(22), chr(23), chr(24), chr(25), chr(26), chr(27), chr(28), chr(29), chr(30), chr(31), // non-printing characters chr(127) ); //replace the unwanted chars $str2 = str_replace($badchar, '', $str); 

直觉上,这看起来好像很快,但情况并非总是如此,你应该确定基准,看看它是否能为你节省任何东西。 我使用随机数据在各种string长度上做了一些基准testing,这个模式出现在php 7.0.12中

  2 chars str_replace 5.3439ms preg_replace 2.9919ms preg_replace is 44.01% faster 4 chars str_replace 6.0701ms preg_replace 1.4119ms preg_replace is 76.74% faster 8 chars str_replace 5.8119ms preg_replace 2.0721ms preg_replace is 64.35% faster 16 chars str_replace 6.0401ms preg_replace 2.1980ms preg_replace is 63.61% faster 32 chars str_replace 6.0320ms preg_replace 2.6770ms preg_replace is 55.62% faster 64 chars str_replace 7.4198ms preg_replace 4.4160ms preg_replace is 40.48% faster 128 chars str_replace 12.7239ms preg_replace 7.5412ms preg_replace is 40.73% faster 256 chars str_replace 19.8820ms preg_replace 17.1330ms preg_replace is 13.83% faster 512 chars str_replace 34.3399ms preg_replace 34.0221ms preg_replace is 0.93% faster 1024 chars str_replace 57.1141ms preg_replace 67.0300ms str_replace is 14.79% faster 2048 chars str_replace 94.7111ms preg_replace 123.3189ms str_replace is 23.20% faster 4096 chars str_replace 227.7029ms preg_replace 258.3771ms str_replace is 11.87% faster 8192 chars str_replace 506.3410ms preg_replace 555.6269ms str_replace is 8.87% faster 16384 chars str_replace 1116.8811ms preg_replace 1098.0589ms preg_replace is 1.69% faster 32768 chars str_replace 2299.3128ms preg_replace 2222.8632ms preg_replace is 3.32% faster 

时间本身是10000次迭代,但更有趣的是相对差异。 多达512个字符,我看到preg_replace总是胜利。 在1-8kb范围内,str_replace具有边缘。

我认为这是一个有趣的结果,所以包括在这里。 重要的是不要拿这个结果,并用它来决定使用哪种方法,而是要根据自己的数据进行基准testing,然后做出决定。

许多其他答案在这里不考虑Unicode字符(例如öäüßйȝîûηыეமிᚉ⠛)。 在这种情况下,您可以使用以下内容:

 $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string); 

\x80-\x9F (字符的7位ASCII范围之上)范围内有一类奇怪的字符,它们在技术上是控制字符,但随着时间的推移,它们被滥用于可打印字符。 如果您对这些没有任何问题,那么您可以使用:

 $string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $string); 

如果您还希望去除换行符,回车符,制表符,不间断空格和软连字符,则可以使用:

 $string = preg_replace('/[\x00-\x1F\x7F-\xA0\xAD]/u', '', $string); 

请注意,您必须对上述示例使用单引号。

如果您希望除了基本可打印的ASCII字符(以上所有示例字符都将被删除),您可以使用:

 $string = preg_replace( '/[^[:print:]]/', '',$string); 

参考见http://www.fileformat.info/info/charset/UTF-8/list.htm

你可以使用字符类

 /[[:cntrl:]]+/ 

这更简单:

$ string = preg_replace('/ [^ [:cntrl:]] /','',$ string);

从PHP 5.2开始,我们也可以访问filter_var,我没有看到任何提及的东西,所以我想把它扔在那里。 要使用filter_var去除不可打印的字符<32和> 127,可以这样做:

筛选32个以下的ASCII字符

 $string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); 

过滤127以上的ASCII字符

 $string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH); 

剥离两者:

 $string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH); 

您也可以在剥离高字符的同时对低字符(换行符,制表符等)进行html编码:

 $string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_LOW|FILTER_FLAG_STRIP_HIGH); 

也有剥离HTML,消毒电子邮件和URL等选项。因此,许多选项(消除数据),甚至validation(如果不是有效的,而不是静静地剥离返回假)。

清洁: http : //php.net/manual/en/filter.filters.sanitize.php

validation: http : //php.net/manual/en/filter.filters.validate.php

然而,仍然存在这样的问题:FILTER_FLAG_STRIP_LOW将去除换行符和回车符,这对于textarea来说是完全有效的字符…所以我猜有些正则expression式的答案在有些时候仍然是必要的,例如在回顾这个之后线程,我打算这样做textareas:

 $string = preg_replace( '/[^[:print:]\r\n]/', '',$input); 

这似乎比数字范围剥离的正则expression式更具可读性。

所有的解决scheme部分工作,甚至低于可能不包括所有的情况。 我的问题是试图插入一个string到UTF8的MySQL表。 string(及其字节)都符合utf8,但有几个不好的序列。 我假设他们大部分是控制或格式。

 function clean_string($string) { $s = trim($string); $s = iconv("UTF-8", "UTF-8//IGNORE", $s); // drop all non utf-8 characters // this is some bad utf-8 byte sequence that makes mysql complain - control and formatting i think $s = preg_replace('/(?>[\x00-\x1F]|\xC2[\x80-\x9F]|\xE2[\x80-\x8F]{2}|\xE2\x80[\xA4-\xA8]|\xE2\x81[\x9F-\xAF])/', ' ', $s); $s = preg_replace('/\s+/', ' ', $s); // reduce all multiple whitespace to a single space return $s; } 

为了进一步加剧问题的表格与服务器与连接与内容的呈现,就像在这里谈论的那样

我的UTF-8兼容版本:

preg_replace('/[^\p{L}\s]/u','',$value);

您可以使用正则expression式来删除您想要保留的字符:

 $string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string); 

replace所有不是(^)字母AZ或az,数字0-9,空格,下划线,hypen,加号和& – 没有任何东西(即删除它)。

 preg_replace('/(?!\n)[\p{Cc}]/', '', $response); 

这将删除所有的控制字符( http://uk.php.net/manual/en/regexp.reference.unicode.php )离开\n换行符。 根据我的经验,控制字符是最经常导致打印问题的字符。

@PaulDixon的答案 完全错误的 ,因为它删除了可打印的 扩展ASCII字符 128-255! 已经部分纠正。 我不知道为什么他仍然想从127字节的7位ASCII集合中删除128-255,因为它没有扩展的ASCII字符。

但最后不要删除128-255,因为例如chr(128)\x80 )是8位ASCII 的欧元符号 ,Windows中的许多UTF-8字体显示一个欧元符号和Android对我自己的testing。

如果从UTF-8string(可能是多字节UTF-8字符的起始字节)中删除ASCII字符128-255,它将杀死许多UTF-8字符。 所以不要这样做! 它们在所有当前使用的文件系统中都是完全合法的。 唯一的保留范围是0-31 。

而是使用它来删除不可打印的字符0-31和127:

 $string = preg_replace('/[\x00-\x1F\x7F]/', '', $string); 

以ASCII和UTF-8工作,因为它们共享相同的控制集合范围 。

不使用正则expression式的速度最快的替代scheme:

 $string = str_replace(array( // control characters chr(0), chr(1), chr(2), chr(3), chr(4), chr(5), chr(6), chr(7), chr(8), chr(9), chr(10), chr(11), chr(12), chr(13), chr(14), chr(15), chr(16), chr(17), chr(18), chr(19), chr(20), chr(21), chr(22), chr(23), chr(24), chr(25), chr(26), chr(27), chr(28), chr(29), chr(30), chr(31), // non-printing characters chr(127) ), '', $string); 

如果要保留所有空白字符\t\n\r ,则从此列表中删除chr(9)chr(10)chr(13) 。 注意:通常的空格是chr(32)所以它保留在结果中。 决定自己是否要删除非破坏空间chr(160)因为它可能会导致问题。

¹由@PaulDixontesting并由我自己validation。

怎么样:

 return preg_replace("/[^a-zA-Z0-9`_.,;@#%~'\"\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:\-\s\\\\]+/", "", $data); 

让我完全控制我想包括的东西

标记的anwser是完美的,但它错过了字符127(DEL),这也是一个不可打印的字符

我的答案是

 $string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string); 

“cedivad”为我解决了这个问题,并得到了瑞典人chaÅÖÖ的不懈努力。

 $text = preg_replace( '/[^\p{L}\s]/u', '', $text ); 

谢谢!

这对我有效。 我不得不将任何forms的string转换为一个search引擎优化。

 function string2Slug($str){ $str = trim($str); $str = str_replace(" ","_",$str); $temp = explode("\\u",$str); $str = ''; foreach ($temp as $bit) { $str .= substr($bit,4); } $str = str_replace("'","",$str); $str = str_replace("\"","",$str); $str = str_replace("\\","",$str); $str = str_replace("\/","",$str); $str = str_replace("/","",$str); $str = str_replace("?","",$str); $str = str_replace("#","",$str); $str = str_replace("&","",$str); $str = str_replace("%","",$str); $str = str_replace("!","",$str); return $str; }