【发布时间】:2010-12-02 15:27:01
【问题描述】:
如何从 PHP 字符串中删除控制字符(如 STX)?我玩过
preg_replace("/[^a-zA-Z0-9 .\-_;!:?äÄöÖüÜß<>='\"]/","",$pString)
但发现它删除了很多。有没有办法删除 only 控制字符?
【问题讨论】:
如何从 PHP 字符串中删除控制字符(如 STX)?我玩过
preg_replace("/[^a-zA-Z0-9 .\-_;!:?äÄöÖüÜß<>='\"]/","",$pString)
但发现它删除了很多。有没有办法删除 only 控制字符?
【问题讨论】:
如果您的意思是控制字符 first 32 ascii characters and \x7F(包括回车等!),那么这将起作用:
preg_replace('/[\x00-\x1F\x7F]/', '', $input);
(注意单引号:用双引号使用\x00 会导致解析错误,不知何故。)
换行符和回车符(通常写成\r 和\n)可以这样保存:
preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $input);
我必须说我认为Bobby's answer 更好,因为[:cntrl:] 比[\x00-\x1F\x7F] 更好地传达了代码的功能。
警告: ereg_replace 在 PHP >= 5.3.0 中已弃用并在 PHP >= 7.0.0 中被删除!请使用 preg_replace 而不是 ereg_replace:
preg_replace('/[[:cntrl:]]/', '', $input);
【讨论】:
对于 Unicode 输入,这将从您的输入文本中删除所有控制字符、未分配的、私人使用的、格式设置和代理代码点(也不是空格字符,例如制表符、换行符)。我用它来从我的输入中删除所有不可打印的字符。
<?php
$clean = preg_replace('/[^\PC\s]/u', '', $input);
有关\p{C} 的更多信息,请参阅http://www.regular-expressions.info/unicode.html#category
【讨论】:
\PC而不是\p{C}?
\p{C}的逆形式
\p{C} 的逆形式,即\PC,所以\p{C} 匹配控制字符,\PC 匹配所有非控制字符。然后我们使用否定字符类[^..] 来表示匹配/替换任何“不是[不是控制字符或空格]”的东西。所以这是一种双重否定。
PHP 确实支持 POSIX-Classes,因此您可以使用 [:cntrl:] 代替一些花哨的字符魔法:
ereg_replace("[:cntrl:]", "", $pString);
编辑:
在 5.3 中可能需要额外的一对方括号。
ereg_replace("[[:cntrl:]]", "", $pString);
【讨论】:
ereg_replace 在 PHP 7.0 中被删除,对于 PHP > 7.0 它应该是:preg_replace("/[[:cntrl:]]/", "", $input);
为了保留控制字符但使它们与 JSON 兼容,我不得不这样做
$str = preg_replace(
array(
'/\x00/', '/\x01/', '/\x02/', '/\x03/', '/\x04/',
'/\x05/', '/\x06/', '/\x07/', '/\x08/', '/\x09/', '/\x0A/',
'/\x0B/','/\x0C/','/\x0D/', '/\x0E/', '/\x0F/', '/\x10/', '/\x11/',
'/\x12/','/\x13/','/\x14/','/\x15/', '/\x16/', '/\x17/', '/\x18/',
'/\x19/','/\x1A/','/\x1B/','/\x1C/','/\x1D/', '/\x1E/', '/\x1F/'
),
array(
"\u0000", "\u0001", "\u0002", "\u0003", "\u0004",
"\u0005", "\u0006", "\u0007", "\u0008", "\u0009", "\u000A",
"\u000B", "\u000C", "\u000D", "\u000E", "\u000F", "\u0010", "\u0011",
"\u0012", "\u0013", "\u0014", "\u0015", "\u0016", "\u0017", "\u0018",
"\u0019", "\u001A", "\u001B", "\u001C", "\u001D", "\u001E", "\u001F"
),
$str
);
(JSON 规则规定:“所有 Unicode 字符都可以放在引号内,但必须转义的字符除外:引号、反斜线和控制字符(U+0000 到 U+001F)。” )
【讨论】:
使用这个正则表达式...
/[^\PCc^\PCn^\PCs]/u
像这样……
$text = preg_replace('/[^\PCc^\PCn^\PCs]/u', '', $text);
^\PCc:不要匹配控制字符。^\PCn:不要匹配未分配的字符。^\PCs:不要匹配 UTF-8 无效字符。简单演示:IDEOne Demo
$text = "\u{0019}hello";
print($text . "\n\n");
$text = preg_replace('/[^\PCc^\PCn^\PCs]/u', '', $text);
print($text);
输出:
(-Broken-Character)hello
hello
^\PC :仅匹配可见字符。不要匹配任何不可见的字符。^\PCc :仅匹配非控制字符。不要匹配任何控制字符。^\PCc^\PCn :仅匹配已分配的非控制字符。不要匹配任何控制或未分配的字符。^\PCc^\PCn^\PCs :仅匹配已分配且 UTF-8 有效的非控制字符。不匹配任何控制、未分配或 UTF-8 无效字符。^\PCc^\PCn^\PCs^\PCf :仅匹配已分配且 UTF-8 有效的非控制、非格式化字符。不匹配任何控制、未分配、格式化或 UTF-8 无效字符。查看可用于在正则表达式中进行测试的Unicode Character Properties。您应该能够在Microsoft .NET、JavaScript、Python、Java、PHP、Ruby、Perl、Golang 甚至Adobe 中使用这些正则表达式。了解 Unicode 字符类是非常容易转移的知识,所以我推荐使用它!
这个正则表达式将匹配任何可见的东西,无论是简写还是长写...
\PL\PM\PN\PP\PS\PZ
\PLetter\PMark\PNumber\PPunctuation\PSymbol\PSeparator
通常\p表示我们要匹配的东西,我们使用\P(大写)to indicate something that does not match.但是PHP没有这个功能,所以我们需要在正则表达式中使用^来做手动否定。
一个更简单的正则表达式将是^\PC,但这在删除不可见格式方面可能过于严格。您可能想仔细观察,看看什么是最好的,但其中一种选择应该适合您的需求。
如果您想了解任何其他可用的字符集,请查看regular-expressions.info...
\PL 或 \PLetter:来自任何语言的任何类型的信件。
\PLl 或 \PLowercase_Letter:带有大写变体的小写字母。\PLu 或 \PUppercase_Letter:带有小写变体的大写字母。\PLt 或 \PTitlecase_Letter:当单词的首字母大写时出现在单词开头的字母。\PL& 或 \PCased_Letter:以小写和大写形式存在的字母(Ll、Lu 和 Lt 的组合)。\PLm 或 \PModifier_Letter:一个特殊字符,像字母一样使用。\PLo 或 \POther_Letter:不区分大小写的字母或表意文字\PM 或 \PMark:旨在与另一个字符组合的字符(例如重音符号、变音符号、封闭框等)。
\PMn 或 \PNon_Spacing_Mark: 用于与另一个字符组合的字符
不占用额外空间的字符(例如重音、变音等)。\PMc 或 \PSpacing_Combining_Mark:旨在与占用额外空间的另一个字符组合的字符(许多东方语言中的元音符号)。\PMe 或 \PEnclosing_Mark:包含与其组合的字符(圆形、方形、键帽等)的字符。\PZ 或 \PSeparator:任何类型的空格或不可见的分隔符。
\PZs 或 \PSpace_Separator:一个不可见但占用空间的空白字符。\PZl 或 \PLine_Separator:行分隔符 U+2028。\PZp 或 \PParagraph_Separator:段落分隔符 U+2029。\PS 或 \PSymbol:数学符号、货币符号、装饰符号、画框字符等。
\PSm 或 \PMath_Symbol:任何数学符号。\PSc 或 \PCurrency_Symbol:任何货币符号。\PSk 或 \PModifier_Symbol:将组合字符(标记)单独作为一个完整字符。\PSo 或 \POther_Symbol:不是数学符号、货币符号或组合字符的各种符号。\PN 或 \PNumber:任何脚本中的任何类型的数字字符。
\PNd 或 \PDecimal_Digit_Number:除表意文字之外的任何文字中的数字 0 到 9。\PNl 或 \PLetter_Number:一个看起来像字母的数字,例如罗马数字。\PNo 或 \POther_Number:上标或下标数字,或不是数字 0-9 的数字(不包括来自表意文字的数字)。\PP 或 \PPunctuation:任何类型的标点符号。
\PPd 或 \PDash_Punctuation:任何类型的连字符或破折号。\PPs 或 \POpen_Punctuation:任何类型的左括号。\PPe 或 \PClose_Punctuation:任何类型的右括号。\PPi 或 \PInitial_Punctuation:任何类型的开场白。\PPf 或 \PFinal_Punctuation:任何类型的结束语。\PPc 或 \PConnector_Punctuation:一个标点符号,例如连接单词的下划线。\PPo 或 \POther_Punctuation:任何非破折号、括号、引号或连接符的标点符号。\PC 或 \POther:不可见的控制字符和未使用的代码点。
\PCc 或 \PControl:ASCII 或 Latin-1 控制字符:0x00–0x1F 和 0x7F–0x9F。\PCf 或 \PFormat:不可见的格式指示符。\PCo 或 \PPrivate_Use:保留供私人使用的任何代码点。\PCs 或 \PSurrogate:UTF-16 编码的代理对的一半。\PCn 或 \PUnassigned:任何未分配字符的代码点。【讨论】:
如果您只是对我熟悉的控制字符(32 岁和 127 岁以下)进行切换,试试这个:
for($control = 0; $control < 32; $control++) {
$pString = str_replace(chr($control), "", $pString;
}
$pString = str_replace(chr(127), "", $pString;
循环删除了除 DEL 之外的所有内容,我们只是将其添加到末尾。
我认为这对你和脚本来说压力会小很多,然后处理正则表达式和正则表达式库。
只是为了好玩,我想出了另一种方法。这个是使用一组控制字符来完成的:
$ctrls = range(chr(0), chr(31));
$ctrls[] = chr(127);
$clean_string = str_replace($ctrls, "", $string);
【讨论】: