我想我需要删除0-31和127字符。
是否有可以高效完成此操作的函数或代码片段?
如果您的Tardis刚落地在1963年,而您只需要7位可打印ASCII字符,则可以使用以下代码来去除0至31和127至255之间的所有内容:
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
它匹配范围在0-31、127-255内的任何字符并将其删除。
你回到了80年代。如果你使用的是某种形式的8位ASCII码,那么你可能希望保留范围在128-255的字符。简单调整一下 - 只需查找0-31和127。
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
欢迎回到21世纪。如果您有一个UTF-8编码的字符串,那么可以在正则表达式上使用/u
修饰符。(参考链接)
$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
这只是删除了0-31和127。这在ASCII和UTF-8中都有效,因为两者共享相同的控制字符集范围(如mgutt在下面指出的)。严格来说,在没有/u
修饰符的情况下也可以工作。但是如果您想删除其他字符,则使用该修饰符会更加方便...
如果您要处理Unicode,则可能会有多种非打印元素,但让我们考虑一个简单的元素:NO-BREAK SPACE (U+00A0)
在UTF-8字符串中,这将被编码为0xC2A0
。您可以查找并删除该特定序列,但是有了放置了/u
修饰符,您可以直接将\xA0
添加到字符类中:
$string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string);
preg_replace非常高效,但如果您需要经常进行此操作,您可以创建一个字符数组来移除所需的字符,并使用如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);
直觉上,这似乎会很快,但并非总是如此,您确实应该进行基准测试以查看它是否能为您节省任何东西。我使用随机数据对各种字符串长度进行了一些基准测试,并且在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略有优势。
我认为这是一个有趣的结果,所以在这里包含它。重要的不是拿这个结果来决定使用哪种方法,而是根据你自己的数据进行基准测试,然后再决定。
这里的许多其他答案没有考虑到 Unicode 字符(例如 öäüßйȝîûηыეமிᚉ⠛)。在这种情况下,可以使用以下代码:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string);
在 \x80-\x9F
范围内(七位 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);
\x7F-\x9F
吗? - Bell自PHP 5.2版本开始,我们也可以使用filter_var函数来过滤非打印字符(小于32和大于127的ASCII字符),但我没有看到任何提及,所以我想在这里提一下。您可以使用以下代码使用filter_var过滤非打印字符(小于32和大于127的ASCII字符):
过滤小于32的ASCII字符
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
过滤掉ASCII字符编码大于127的字符
$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等的选项。因此,有很多用于净化(删除数据)甚至验证(如果不合法则返回false而不是静默删除)的选项。
净化:http://php.net/manual/en/filter.filters.sanitize.php
验证:http://php.net/manual/en/filter.filters.validate.php
但是,仍然存在问题,即FILTER_FLAG_STRIP_LOW将剥离换行符和回车符,而对于文本区域来说,这些字符完全是有效的... 所以一些正则表达式的答案在某些情况下仍然是必要的,例如,在检查了这个线程之后,我打算为文本区域执行以下操作:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
这个看起来比一些通过数值范围剥离的正则表达式更易读。
你可以使用字符类
/[[:cntrl:]]+/
所有的解决方案都只是部分有效,甚至下面的解决方案可能也不能涵盖所有情况。我的问题是尝试将一个字符串插入到一个utf8 mysql表中。该字符串(及其字节)都符合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;
}
为了进一步加剧问题,涉及到内容的表格、服务器、连接和渲染如此处稍微讨论
$s = preg_replace('/(\xF0\x9F[\x00-\xFF][\x00-\xFF])/', ' ', $s);
。 - Joe Black这段代码是用于将字符串中非控制字符的地方替换为空格。$string = preg_replace('/[^[:cntrl:]]/', '',$string);
从输入字符串中删除所有非ASCII字符
$result = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
该代码移除十六进制范围在0-31和128-255之间的任何字符,只留下结果字符串中十六进制32-127的字符,在这个例子中称为$result。
[\x00-\x1F\x7F-\xFF]
是否更好? - Volomike对于UTF-8,可以尝试以下代码:
preg_replace('/[^\p{L}\s]/u','', $string);
这是我10年前的原始答案,正如评论所说,它非常适合用于全文搜索引擎,因为它会移除一些非文本可打印字符,例如[]!~等。
如果你还需要删除无效字符以供 libexpat
(叹气)使用,可以尝试以下代码:
preg_replace('/[^\PCc^\PCn^\PCs]/u', '', $string);
有关该方法的详细信息,请参见此答案。
$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);
使用正则表达式替换除字母A-Z或a-z、数字0-9、空格、下划线、连字符、加号和&符号以外的所有字符为空(即删除)。
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
\n
换行符。从我的经验来看,控制字符是最常引起打印问题的字符。/u
。您能否解释一下第一部分(?!\n)
的作用? - Marcio Mazzucato