从 PHP 字符串中删除控制字符

我怎样才能从 PHP 字符串中删除像 STX 这样的控制字符

preg_replace("/[^a-zA-Z0-9 .\-_;!:?äÄöÖüÜß<>='\"]/","",$pString)

但是发现它删除的方式太多了。有没有办法只删除 < em > 控制字符?

89135 次浏览

PHP 确实支持 POSIX-Class,因此您可以使用 [:cntrl:]而不是一些花哨的字符-魔术-东西:

ereg_replace("[:cntrl:]", "", $pString);

编辑:

在5.3中可能需要额外的一对方括号。

ereg_replace("[[:cntrl:]]", "", $pString);

如果你所说的控制字符是指 前32个字符和 \x7F(包括回车符等) ,那么这样就可以了:

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

(注意单引号: 使用双引号时,\x00的使用会以某种方式导致解析错误。)

行馈送和回车(通常写为 \r\n)可以像下面这样保存:

preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $input);

我必须说,我认为 鲍比的回答更好,在这个意义上,[:cntrl:][\x00-\x1F\x7F]更好地传达代码的功能。

警告: ereg_replace在 PHP > = 5.3.0中被弃用,在 PHP > = 7.0.0中被删除! 请使用 preg_replace而不是 ereg_replace:

preg_replace('/[[:cntrl:]]/', '', $input);

无正则表达式的方法

如果你只是想杀死我熟悉的控制字符(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);

为了保留控件字符,但使它们与 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)。”)

对于 Unicode 输入,这将从输入文本中删除所有控制字符、未分配的、私有使用的、格式化和代理代码点(这些代码点也不是空格字符,如制表符、新行)。我使用它来从输入中删除所有不可打印的字符。

<?php
$clean = preg_replace('/[^\PC\s]/u', '', $input);

有关 \p{C}的详细信息,请参阅 http://www.regular-expressions.info/unicode.html#category

TLDR 答案

用这个正则..。

/[^\PCc^\PCn^\PCs]/u

像这样..。

$text = preg_replace('/[^\PCc^\PCn^\PCs]/u', '', $text);

TLDR 说明

  • ^\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字符。您应该能够在 微软.NETJavaScript巨蟒爪哇咖啡PHP露比Perl戈兰甚至 Adobe中使用这些正则表达式。了解 Unicode字符是 微软.NET0,所以我推荐使用它!

这个正则表达式将匹配任何可见的东西,无论是短手形式还是长手形式..。

\PL\PM\PN\PP\PS\PZ
\PLetter\PMark\PNumber\PPunctuation\PSymbol\PSeparator

通常,\p表示它是我们想要匹配的,我们使用 \P(大写) 指示与 < em > 不匹配的内容。 ,但 PHP 没有这个功能,所以我们需要在正则表达式中使用 ^来进行手动否定。

一个更简单的正则表达式是 ^\PC,但是这在删除不可见格式方面可能限制太多。你可能想仔细观察,看看什么是最好的,但其中一个选择应该适合你的需要。

所有可匹配的 Unicode字符集

如果你想知道任何其他字符集可用,检查 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: 任何类型的空格或不可见分隔符。
    • 一个看不见的空白字符,但是确实会占用空间。
    • \PZl\PLine_Separator: 行分隔符 U + 2028。
    • \PZp\PParagraph_Separator: 段落分隔符 U + 2029。
  • \PS \PSymbol: 数学符号、货币符号、丁贝、方框字符等。
    • \PSm\PMath_Symbol: 任何数学符号。
    • \PSc\PCurrency_Symbol: 任何货币符号。
    • Abc0或 \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 or \POpen_Punctuation: any kind of opening bracket.
    • \PPe\PClose_Punctuation: 任何类型的闭合支架。
    • \PPi\PInitial_Punctuation: 任何类型的开场报价。
    • \PPf\PFinal_Punctuation: 任何类型的结束报价。
    • \PPc\PConnector_Punctuation: 连接单词的标点符号,如下划线。
    • \PPo\POther_Punctuation: 任何不是破折号、括号、引号或连接符的标点符号。
  • \PC \POther: 不可见的控制字符和未使用的代码点。
    • \PCc\PControl: ASCII 或拉丁文 -1控制字符: 0x00-0x1F 和0x7F-0x9F。
    • \PCf\PFormat: 不可见的格式指示器。
    • \PCo\PPrivate_Use: 为私人使用保留的任何代码点。
    • \PCs\PSurrogate: UTF-16编码的代理对的一半。
    • \PCn\PUnassigned: 任何没有指定字符的代码点。