Saya membayangkan saya perlu menghapus karakter 0-31 dan 127,
Apakah ada fungsi atau potongan kode untuk melakukan ini secara efisien.
Saya membayangkan saya perlu menghapus karakter 0-31 dan 127,
Apakah ada fungsi atau potongan kode untuk melakukan ini secara efisien.
Jawaban:
Jika Tardis Anda baru saja mendarat pada tahun 1963, dan Anda hanya ingin 7-bit ASCII char yang dapat dicetak, Anda dapat merobek semuanya dari 0-31 dan 127-255 dengan ini:
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
Ini cocok dengan apa pun dalam kisaran 0-31, 127-255 dan menghapusnya.
Anda jatuh ke dalam Hot Tub Time Machine, dan Anda kembali di tahun delapan puluhan. Jika Anda memiliki beberapa bentuk ASCII 8 bit, maka Anda mungkin ingin menyimpan karakter dalam kisaran 128-255. Penyesuaian mudah - hanya mencari 0-31 dan 127
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Ah, selamat datang kembali ke abad ke-21. Jika Anda memiliki string yang dikodekan UTF-8, maka /u
pengubahnya dapat digunakan pada regex
$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
Ini hanya menghilangkan 0-31 dan 127. Ini bekerja di ASCII dan UTF-8 karena keduanya berbagi rentang set kontrol yang sama (seperti dicatat oleh mgutt di bawah). Sebenarnya, ini akan bekerja tanpa /u
pengubah. Tapi itu membuat hidup lebih mudah jika Anda ingin menghapus karakter lain ...
Jika Anda berurusan dengan Unicode, ada banyak elemen non-cetak yang berpotensi , tetapi mari pertimbangkan yang sederhana: RUANG TANPA BREAK (U + 00A0)
Dalam string UTF-8, ini akan dikodekan sebagai 0xC2A0
. Anda bisa mencari dan menghapus urutan tertentu, tetapi dengan /u
pengubah di tempat, Anda bisa menambahkan \xA0
ke kelas karakter:
$string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string);
preg_replace cukup efisien, tetapi jika Anda sering melakukan operasi ini, Anda bisa membuat array karakter yang ingin Anda hapus, dan menggunakan str_replace seperti dicatat oleh mgutt di bawah ini, mis.
//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);
Secara intuitif, ini sepertinya cepat, tetapi tidak selalu demikian, Anda harus melakukan tolok ukur untuk melihat apakah itu menyelamatkan Anda. Saya melakukan beberapa tolok ukur di berbagai panjang string dengan data acak, dan pola ini muncul menggunakan 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
Pengaturan waktu sendiri untuk 10.000 iterasi, tetapi yang lebih menarik adalah perbedaan relatifnya. Hingga 512 karakter, saya melihat preg_replace alway win. Dalam rentang 1-8kb, str_replace memiliki tepi marjinal.
Saya pikir itu hasil yang menarik, jadi termasuk di sini. Yang penting adalah tidak mengambil hasil ini dan menggunakannya untuk memutuskan metode mana yang akan digunakan, tetapi untuk membandingkan data Anda sendiri dan kemudian memutuskan.
Banyak jawaban lain di sini tidak memperhitungkan karakter unicode (mis. Öäüßйȝîûηы ე மி ᚉ ⠛). Dalam hal ini Anda dapat menggunakan yang berikut:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string);
Ada kelas karakter yang aneh dalam rentang \x80-\x9F
(Tepat di atas rentang ASCII 7-bit karakter) yang secara teknis mengontrol karakter, tetapi seiring waktu telah disalahgunakan untuk karakter yang dapat dicetak. Jika Anda tidak memiliki masalah dengan ini, maka Anda dapat menggunakan:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $string);
Jika Anda juga ingin menghapus feed garis, carriage return, tab, spasi tanpa putus, dan tanda hubung lunak, Anda dapat menggunakan:
$string = preg_replace('/[\x00-\x1F\x7F-\xA0\xAD]/u', '', $string);
Perhatikan bahwa Anda harus menggunakan tanda kutip tunggal untuk contoh di atas.
Jika Anda ingin menghapus semuanya kecuali karakter ASCII dasar yang dapat dicetak (semua karakter contoh di atas akan dilucuti) Anda dapat menggunakan:
$string = preg_replace( '/[^[:print:]]/', '',$string);
Untuk referensi lihat http://www.fileformat.info/info/charset/UTF-8/list.htm
'/[\x00-\x1F\x80-\xC0]/u'
biarkan mereka utuh; tetapi juga tanda pembagian (F7) dan multiplikasi (D7).
\x7F-\x9F
?
Dimulai dengan PHP 5.2, kami juga memiliki akses ke filter_var, yang saya belum melihat menyebutkan jadi saya akan membuangnya di sana. Untuk menggunakan filter_var untuk menghapus karakter yang tidak dapat dicetak <32 dan> 127, Anda dapat melakukan:
Saring karakter ASCII di bawah 32
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
Saring karakter ASCII di atas 127
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH);
Lepaskan keduanya:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
Anda juga dapat menyandikan-html karakter rendah (baris baru, tab, dll.) Sambil menelanjangi tinggi:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_LOW|FILTER_FLAG_STRIP_HIGH);
Ada juga opsi untuk menghapus HTML, membersihkan email dan URL, dll. Jadi, banyak pilihan untuk sanitasi (menghapus data) dan bahkan validasi (mengembalikan false jika tidak valid daripada stripping diam-diam).
Sanitasi: http://php.net/manual/en/filter.filters.sanitize.php
Validasi: http://php.net/manual/en/filter.filters.validate.php
Namun, masih ada masalah, bahwa FILTER_FLAG_STRIP_LOW akan menghapus baris baru dan pengembalian carriage, yang untuk textarea adalah karakter yang benar-benar valid ... jadi beberapa jawaban Regex, saya kira, masih diperlukan pada waktu-waktu tertentu, misalnya setelah meninjau ini utas, saya berencana untuk melakukan ini untuk textareas:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
Ini tampaknya lebih mudah dibaca daripada sejumlah regex yang dilucuti oleh rentang numerik.
Anda dapat menggunakan kelas karakter
/[[:cntrl:]]+/
ini lebih sederhana:
$ string = preg_replace ('/ [^ [: cntrl:]] /', '', $ string);
Semua solusi bekerja sebagian, dan bahkan di bawah ini mungkin tidak mencakup semua kasus. Masalah saya adalah mencoba memasukkan string ke tabel mysql utf8. String (dan bytes-nya) semuanya sesuai dengan utf8, tetapi memiliki beberapa urutan yang buruk. Saya berasumsi bahwa kebanyakan dari mereka adalah kontrol atau pemformatan.
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;
}
Untuk lebih memperburuk masalah adalah tabel vs server vs koneksi vs rendering konten, seperti yang dibicarakan di sini
$s = preg_replace('/(\xF0\x9F[\x00-\xFF][\x00-\xFF])/', ' ', $s);
karena semua karakter emoji mengacaukan mysql
Versi yang sesuai dengan UTF-8 saya:
preg_replace('/[^\p{L}\s]/u','',$value);
Anda dapat menggunakan ekspres reguler untuk menghapus semuanya selain dari karakter yang ingin Anda pertahankan:
$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);
Mengganti segala sesuatu yang bukan (^) huruf AZ atau az, angka 0-9, spasi, garis bawah, tanda hubung, plus dan ampersand - dengan tidak ada (yaitu menghapusnya).
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
Ini akan menghapus semua karakter kontrol ( http://uk.php.net/manual/en/regexp.reference.unicode.php ) meninggalkan \n
karakter baris baru. Dari pengalaman saya, karakter kontrol adalah yang paling sering menyebabkan masalah pencetakan.
/u
untuk karakter UTF-8. Bisakah Anda jelaskan apa yang (?!\n)
dilakukan bagian pertama ?
Untuk menghapus semua karakter non-ASCII dari string input
$result = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
Kode itu menghilangkan karakter apa pun dalam rentang hex 0-31 dan 128-255, hanya menyisakan karakter hex 32-127 dalam string yang dihasilkan, yang saya sebut $ hasil dalam contoh ini.
The jawaban @PaulDixon adalah benar-benar salah , karena menghilangkan dicetak karakter ASCII diperpanjang 128-255!telah diperbaiki sebagian. Saya tidak tahu mengapa dia masih ingin menghapus 128-255 dari 127 karakter ASCII 7-bit yang ditetapkan karena tidak memiliki karakter ASCII yang diperluas.
Tetapi akhirnya penting untuk tidak menghapus 128-255 karena misalnya chr(128)
( \x80
) adalah tanda euro dalam ASCII 8-bit dan banyak font UTF-8 di Windows menampilkan tanda euro dan Android mengenai pengujian saya sendiri.
Dan itu akan membunuh banyak karakter UTF-8 jika Anda menghapus karakter ASCII 128-255 dari string UTF-8 (mungkin byte awal dari karakter UTF-8 multi-byte). Jadi jangan lakukan itu! Mereka adalah karakter yang sepenuhnya legal di semua sistem file yang saat ini digunakan. Kisaran yang hanya dipesan adalah 0-31 .
Alih-alih gunakan ini untuk menghapus karakter yang tidak dapat dicetak 0-31 dan 127:
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Ia bekerja di ASCII dan UTF-8 karena keduanya berbagi rentang set kontrol yang sama .
The tercepat alternatif slower¹ tanpa menggunakan ekspresi reguler:
$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);
Jika Anda ingin menyimpan semua karakter spasi putih \t
, \n
dan \r
, lalu hapus chr(9)
, chr(10)
dan chr(13)
dari daftar ini. Catatan: Ruang kosong yang biasa chr(32)
jadi tetap di hasilnya. Putuskan sendiri apakah Anda ingin menghapus ruang yang tidak putus chr(160)
karena dapat menyebabkan masalah.
¹ Diuji oleh @PaulDixon dan diverifikasi sendiri.
Browser ditandai sempurna tetapi melewatkan karakter 127 (DEL) yang juga merupakan karakter yang tidak dapat dicetak
jawaban saya adalah
$string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string);
"cedivad" memecahkan masalah bagi saya dengan hasil terus-menerus dari karakter Swedia ÅÄÖ.
$text = preg_replace( '/[^\p{L}\s]/u', '', $text );
Terima kasih!
Bagi siapa pun yang masih mencari cara untuk melakukan ini tanpa menghapus karakter yang tidak dapat dicetak, tetapi melarikan diri, saya membuat ini untuk membantu. Jangan ragu untuk memperbaikinya! Karakter diloloskan ke \\ x [A-F0-9] [A-F0-9].
Sebut seperti ini:
$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));
}
?>
Saya memecahkan masalah untuk UTF8 menggunakan https://github.com/neitanod/forceutf8
use ForceUTF8\Encoding;
$string = Encoding::fixUTF8($string);
Regex ke jawaban yang dipilih gagal untuk Unicode: 0x1d (dengan php 7.4)
sebuah solusi:
<?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 String menghapus semua karakter yang tidak terlihat kecuali baris baru