Answers:
如果您的Tardis刚好在1963年登陆,并且您只想要7位可打印的ASCII字符,则可以使用以下方法从0-31和127-255中删除所有内容:
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
它匹配0-31、127-255范围内的任何内容并将其删除。
您掉进了热水浴缸计时机,而您又回到了八十年代。如果您具有某种形式的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
(在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
'/[\x00-\x1F\x80-\xC0]/u'
使它们完好无损;而且还有除法(F7)和乘法(D7)符号。
\x7F-\x9F
吗?
从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等的选项。因此,存在许多用于清除(剥离数据)甚至进行验证的选项(如果无效则返回false,而不是静默剥离)。
消毒: http : //php.net/manual/en/filter.filters.sanitize.php
验证: http //php.net/manual/en/filter.filters.validate.php
但是,仍然存在问题,即FILTER_FLAG_STRIP_LOW会去除换行符和回车符,对于textarea来说,它们是完全有效的字符...因此,我想某些Regex答案有时还是有必要的,例如,在检查了此内容之后线程,我打算为textareas做到这一点:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
这似乎比按数字范围删除的许多正则表达式更具可读性。
这更简单:
$ string = preg_replace('/ [^ [:cntrl:]] /','',$ string);
所有解决方案都部分起作用,甚至以下解决方案也无法涵盖所有情况。我的问题是试图在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);
,因为所有的表情符被搞乱了MySQL的
我的UTF-8兼容版本:
preg_replace('/[^\p{L}\s]/u','',$value);
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
这将删除所有控制字符(http://uk.php.net/manual/en/regexp.reference.unicode.php),并保留\n
换行符。根据我的经验,控制字符是最经常导致打印问题的字符。
/u
了UTF-8字符。您能否解释一下第一部分的内容(?!\n)
?
从输入字符串中剥离所有非ASCII字符
$result = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
该代码删除了十六进制范围0-31和128-255中的任何字符,只在结果字符串中保留了十六进制字符32-127,在本示例中,我将其称为$ result。
@PaulDixon 的答案是完全错误的,因为它删除了可打印的 扩展ASCII字符 128-255!已经部分纠正。我不知道他为什么仍要从127个字符的7位ASCII集中删除128-255,因为它没有扩展的ASCII字符。
但最后重要的是不要删除128-255,因为例如chr(128)
(\x80
)是8位ASCII 的欧元符号,而Windows中的许多UTF-8字体在我自己的测试中均显示欧元符号,而Android则显示 Android。
如果您从UTF-8字符串(可能是多字节UTF-8字符的起始字节)中删除ASCII字符128-255,它将杀死许多UTF-8字符。所以不要那样做!在所有当前使用的文件系统中,它们完全是合法字符。唯一保留的范围是0-31。
而是使用此命令删除不可打印的字符0-31和127:
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
它可用于ASCII和UTF-8,因为它们共享相同的控件集范围。
不使用正则表达式的最快的慢速¹替代项:
$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)
因为这会引起问题。
¹由@PaulDixon测试,并由我自己验证。
标记的anwser是完美的,但它错过了字符127(DEL),后者也是不可打印的字符
我的答案是
$string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string);
“ cedivad”凭借瑞典字符ÅÄÖ的持久结果为我解决了这个问题。
$text = preg_replace( '/[^\p{L}\s]/u', '', $text );
谢谢!
对于仍在寻找如何做到这一点而不删除不可打印字符,而是转义它们的任何人,我提供了此帮助。随时进行改进!字符转义为\\ x [A-F0-9] [A-F0-9]。
像这样打电话:
$escaped = EscapeNonASCII($string);
$unescaped = UnescapeNonASCII($string);
<?php
function EscapeNonASCII($string) //Convert string to hex, replace non-printable chars with escaped hex
{
$hexbytes = strtoupper(bin2hex($string));
$i = 0;
while ($i < strlen($hexbytes))
{
$hexpair = substr($hexbytes, $i, 2);
$decimal = hexdec($hexpair);
if ($decimal < 32 || $decimal > 126)
{
$top = substr($hexbytes, 0, $i);
$escaped = EscapeHex($hexpair);
$bottom = substr($hexbytes, $i + 2);
$hexbytes = $top . $escaped . $bottom;
$i += 8;
}
$i += 2;
}
$string = hex2bin($hexbytes);
return $string;
}
function EscapeHex($string) //Helper function for EscapeNonASCII()
{
$x = "5C5C78"; //\x
$topnibble = bin2hex($string[0]); //Convert top nibble to hex
$bottomnibble = bin2hex($string[1]); //Convert bottom nibble to hex
$escaped = $x . $topnibble . $bottomnibble; //Concatenate escape sequence "\x" with top and bottom nibble
return $escaped;
}
function UnescapeNonASCII($string) //Convert string to hex, replace escaped hex with actual hex.
{
$stringtohex = bin2hex($string);
$stringtohex = preg_replace_callback('/5c5c78([a-fA-F0-9]{4})/', function ($m) {
return hex2bin($m[1]);
}, $stringtohex);
return hex2bin(strtoupper($stringtohex));
}
?>
我使用https://github.com/neitanod/forceutf8解决了UTF8的问题
use ForceUTF8\Encoding;
$string = Encoding::fixUTF8($string);
将正则表达式转换为Unicode的所选答案失败:0x1d(使用php 7.4)
一个办法:
<?php
$ct = 'différents'."\r\n test";
// fail for Unicode: 0x1d
$ct = preg_replace('/[\x00-\x1F\x7F]$/u', '',$ct);
// work for Unicode: 0x1d
$ct = preg_replace( '/[^\P{C}]+/u', "", $ct);
// work for Unicode: 0x1d and allow line break
$ct = preg_replace( '/[^\P{C}\n]+/u', "", $ct);
echo $ct;
from: UTF 8字符串删除除换行符以外的所有不可见字符