文字0〜31と127を削除する必要があると思います。
これを効率的に行うための関数またはコードの一部はありますか?
文字0〜31と127を削除する必要があると思います。
これを効率的に行うための関数またはコードの一部はありますか?
回答:
Tardisが1963年に上陸したばかりで、7ビットの印刷可能なASCII文字が必要な場合は、次のようにして0〜31と127〜255のすべてをリッピングできます。
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
0〜31、127〜255の範囲のすべてに一致し、削除されます。
あなたはHot Tub Time Machineに陥り、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〜8 kbの範囲では、str_replaceに限界エッジがありました。
面白い結果だと思ったのでここに入れておきます。重要なことは、この結果を使用して、使用する方法を決定するために使用するのではなく、独自のデータに対してベンチマークしてから決定することです。
ここでの他の回答の多くはユニコード文字を考慮していません(例öäüßйȝîûηыეமிᚉ⠛)。この場合、以下を使用できます。
$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の場合は完全に有効な文字です。したがって、たとえばこれを確認した後、一部の正規表現の回答がまだ必要な場合があります。スレッド、私は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);
このコードは、16進数の範囲0〜31および128〜255のすべての文字を削除し、結果の文字列に16進数の32〜127のみを残します。この例では、$ resultと呼んでいます。
@PaulDixon の答えは完全に間違っています。印刷可能な 拡張ASCII文字 128〜255が削除されるためです。部分的に修正されました。拡張ASCII文字がないため、127文字の7ビットASCIIセットから128-255を削除する理由を私は知りません。
しかし、最後に128-255を削除しないことが重要でした。たとえば、chr(128)
(\x80
)は8ビットASCII のユーロ記号であり、Windowsの多くのUTF-8フォントは、自分のテストに関してユーロ記号と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で動作します。
正規表現を使用しない、最も遅い slowの代替案:
$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);
印刷不可能な文字を削除せずにエスケープする方法をまだ探している人のために、それらをエスケープするために、私はこれを手助けするために作りました。自由に改善してください!文字は\\ 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;