Tôi tưởng tượng tôi cần xóa ký tự 0-31 và 127,
Có một chức năng hoặc đoạn mã để làm điều này một cách hiệu quả.
Tôi tưởng tượng tôi cần xóa ký tự 0-31 và 127,
Có một chức năng hoặc đoạn mã để làm điều này một cách hiệu quả.
Câu trả lời:
Nếu Tardis của bạn vừa hạ cánh vào năm 1963 và bạn chỉ muốn các ký tự ASCII có thể in 7 bit, bạn có thể trích xuất mọi thứ từ 0-31 và 127-255 bằng cách này:
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
Nó phù hợp với bất cứ điều gì trong phạm vi 0-31, 127-255 và loại bỏ nó.
Bạn rơi vào cỗ máy thời gian bồn tắm nóng, và bạn trở lại những năm tám mươi. Nếu bạn đã có một số dạng ASCII 8 bit, thì bạn có thể muốn giữ các ký tự trong phạm vi 128-255. Một điều chỉnh dễ dàng - chỉ cần tìm 0-31 và 127
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Ah, chào mừng trở lại thế kỷ 21. Nếu bạn có chuỗi được mã hóa UTF-8, thì công cụ /u
sửa đổi có thể được sử dụng trên regex
$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
Điều này chỉ loại bỏ 0-31 và 127. Điều này hoạt động trong ASCII và UTF-8 vì cả hai đều có chung phạm vi điều khiển (như được ghi chú bởi mgutt bên dưới). Nói đúng ra, cái này sẽ hoạt động mà không cần /u
sửa đổi. Nhưng nó làm cho cuộc sống dễ dàng hơn nếu bạn muốn loại bỏ các ký tự khác ...
Nếu bạn đang xử lý Unicode, có khả năng có nhiều yếu tố không in , nhưng hãy xem xét một yếu tố đơn giản: KHÔNG GIAN KHÔNG GIỐNG (U + 00A0)
Trong chuỗi UTF-8, điều này sẽ được mã hóa thành 0xC2A0
. Bạn có thể tìm và loại bỏ chuỗi cụ thể đó, nhưng với công cụ /u
sửa đổi tại chỗ, bạn chỉ cần thêm \xA0
vào lớp ký tự:
$string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string);
preg numplace khá hiệu quả, nhưng nếu bạn thực hiện thao tác này nhiều, bạn có thể tạo một mảng các ký tự bạn muốn xóa và sử dụng str numplace như được ghi chú bởi mgutt bên dưới, ví dụ:
//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);
Theo trực giác, điều này có vẻ như sẽ nhanh, nhưng không phải lúc nào cũng vậy, bạn chắc chắn nên điểm chuẩn để xem nó có giúp bạn tiết kiệm được gì không. Tôi đã thực hiện một số điểm chuẩn qua nhiều độ dài chuỗi khác nhau với dữ liệu ngẫu nhiên và mẫu này đã xuất hiện bằng cách sử dụng 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
Bản thân thời gian là 10000 lần lặp, nhưng điều thú vị hơn là sự khác biệt tương đối. Lên đến 512 ký tự, tôi đã thấy preg numplace luôn giành chiến thắng. Trong phạm vi 1-8kb, str numplace có lợi thế biên.
Tôi nghĩ rằng đó là kết quả thú vị, vì vậy bao gồm nó ở đây. Điều quan trọng không phải là lấy kết quả này và sử dụng nó để quyết định sử dụng phương pháp nào, mà là điểm chuẩn so với dữ liệu của chính bạn và sau đó quyết định.
Nhiều câu trả lời khác ở đây không tính đến các ký tự unicode (ví dụ: öäüßйȝîûηы ე). Trong trường hợp này, bạn có thể sử dụng như sau:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string);
Có một lớp nhân vật kỳ lạ trong phạm vi \x80-\x9F
(Chỉ trên phạm vi ký tự ASCII 7 bit) là các ký tự điều khiển kỹ thuật, nhưng theo thời gian đã bị sử dụng sai cho các ký tự có thể in được. Nếu bạn không có bất kỳ vấn đề nào với những thứ này, thì bạn có thể sử dụng:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $string);
Nếu bạn cũng muốn loại bỏ nguồn cấp dữ liệu, trả về vận chuyển, tab, không gian không phá vỡ và dấu gạch nối mềm, bạn có thể sử dụng:
$string = preg_replace('/[\x00-\x1F\x7F-\xA0\xAD]/u', '', $string);
Lưu ý rằng bạn phải sử dụng dấu ngoặc đơn cho các ví dụ trên.
Nếu bạn muốn loại bỏ mọi thứ trừ các ký tự ASCII có thể in cơ bản (tất cả các ký tự mẫu ở trên sẽ bị xóa), bạn có thể sử dụng:
$string = preg_replace( '/[^[:print:]]/', '',$string);
Để tham khảo xem http://www.fileformat.info/info/charset/UTF-8/list.htmlm
'/[\x00-\x1F\x80-\xC0]/u'
để chúng nguyên vẹn; nhưng cũng có dấu phân chia (F7) và phép nhân (D7).
\x7F-\x9F
?
Bắt đầu với PHP 5.2, chúng tôi cũng có quyền truy cập vào bộ lọc_var mà tôi chưa thấy đề cập đến vì vậy tôi nghĩ rằng tôi sẽ ném nó ra khỏi đó. Để sử dụng bộ lọc_var để loại bỏ các ký tự không in được <32 và> 127, bạn có thể thực hiện:
Lọc các ký tự ASCII dưới 32
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
Lọc các ký tự ASCII trên 127
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH);
Dải cả hai:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
Bạn cũng có thể mã hóa các ký tự thấp html (dòng mới, tab, v.v.) trong khi tước cao:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_LOW|FILTER_FLAG_STRIP_HIGH);
Ngoài ra còn có các tùy chọn để tước HTML, khử trùng e-mail và URL, v.v.
Vệ sinh: http://php.net/manual/en/filter.filters.sanitize.php
Xác thực: http://php.net/manual/en/filter.filters.validate.php
Tuy nhiên, vẫn còn một vấn đề, đó là FILTER_FLAG_STRIP_LOW sẽ loại bỏ các dòng mới và trả về vận chuyển, mà đối với một văn bản là các ký tự hoàn toàn hợp lệ ... do đó, một số câu trả lời của Regex, đôi khi vẫn cần thiết, ví dụ như sau khi xem xét chủ đề, tôi dự định làm điều này cho textareas:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
Điều này có vẻ dễ đọc hơn một số biểu thức được loại bỏ theo phạm vi số.
bạn có thể sử dụng các lớp nhân vật
/[[:cntrl:]]+/
Điều này đơn giản hơn:
$ string = preg numplace ('/ [^ [: cntrl:]] /', '', $ string);
Tất cả các giải pháp hoạt động một phần, và thậm chí dưới đây có thể không bao gồm tất cả các trường hợp. Vấn đề của tôi là trong việc cố gắng chèn một chuỗi vào bảng mysf utf8. Chuỗi (và byte của nó) đều tuân thủ utf8, nhưng có một vài chuỗi xấu. Tôi cho rằng hầu hết trong số họ là kiểm soát hoặc định dạng.
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;
}
Để làm trầm trọng thêm vấn đề là bảng so với máy chủ so với kết nối so với kết xuất nội dung, như đã nói về một chút ở đây
$s = preg_replace('/(\xF0\x9F[\x00-\xFF][\x00-\xFF])/', ' ', $s);
vì tất cả các nhân vật biểu tượng cảm xúc đã làm rối tung mysql
Phiên bản tuân thủ UTF-8 của tôi:
preg_replace('/[^\p{L}\s]/u','',$value);
Bạn có thể sử dụng biểu thức chính quy để xóa mọi thứ ngoài các ký tự bạn muốn giữ:
$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);
Thay thế mọi thứ không phải (^) các chữ cái AZ hoặc az, các số 0-9, dấu cách, dấu gạch dưới, hypen, dấu cộng và ký hiệu - không có gì (ví dụ: xóa nó).
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
Thao tác này sẽ xóa tất cả các ký tự điều khiển ( http://uk.php.net/manual/en/regapi.reference.unicode.php ) để lại các \n
ký tự dòng mới. Từ kinh nghiệm của tôi, các ký tự điều khiển là những ký tự thường gây ra sự cố in ấn.
/u
cho ký tự UTF-8. Bạn có thể vui lòng giải thích những gì phần đầu tiên (?!\n)
làm?
Để loại bỏ tất cả các ký tự không phải ASCII khỏi chuỗi đầu vào
$result = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
Mã đó sẽ loại bỏ bất kỳ ký tự nào trong các phạm vi hex 0-31 và 128-255, chỉ để lại các ký tự hex 32-127 trong chuỗi kết quả, mà tôi gọi là $ result trong ví dụ này.
Câu trả lời của @PaulDixon là hoàn toàn sai , bởi vì nó loại bỏ các ký tự ASCII mở rộng có thể in 128-255! đã được sửa chữa một phần. Tôi không biết tại sao anh ta vẫn muốn xóa 128-255 khỏi bộ ASCII 127 bit có ký tự 127 vì nó không có các ký tự ASCII mở rộng.
Nhưng cuối cùng, điều quan trọng là không xóa 128-255 vì ví dụ chr(128)
( \x80
) là ký hiệu euro trong ASCII 8 bit và nhiều phông chữ UTF-8 trong Windows hiển thị ký hiệu euro và Android liên quan đến thử nghiệm của riêng tôi.
Và nó sẽ giết nhiều ký tự UTF-8 nếu bạn xóa ký tự ASCII 128-255 khỏi chuỗi UTF-8 (có thể là byte bắt đầu của ký tự UTF-8 nhiều byte). Vì vậy, đừng làm điều đó! Chúng là các ký tự hoàn toàn hợp pháp trong tất cả các hệ thống tệp hiện đang sử dụng. Phạm vi dành riêng duy nhất là 0-31 .
Thay vào đó, hãy sử dụng để xóa các ký tự không in được 0-31 và 127:
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Nó hoạt động trong ASCII và UTF-8 vì cả hai đều có chung phạm vi điều khiển .
Cách thay thế chậm nhất nhanh nhất mà không sử dụng biểu thức thông thường:
$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);
Nếu bạn muốn giữ lại tất cả các ký tự khoảng trắng \t
, \n
và \r
, sau đó loại bỏ chr(9)
, chr(10)
và chr(13)
từ danh sách này. Lưu ý: Khoảng trắng thông thường là chr(32)
để nó nằm trong kết quả. Tự quyết định nếu bạn muốn loại bỏ không gian không phá vỡ chr(160)
vì nó có thể gây ra vấn đề.
Được thử nghiệm bởi @PaulDixon và được xác minh bởi chính tôi.
Đánh dấu anwser là hoàn hảo nhưng nó bỏ lỡ ký tự 127 (DEL) cũng là một ký tự không in được
câu trả lời của tôi sẽ là
$string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string);
Đối với bất cứ ai vẫn đang tìm cách làm điều này mà không loại bỏ các ký tự không in được, nhưng thoát khỏi chúng, tôi đã làm điều này để giúp đỡ. Hãy cải thiện nó! Các ký tự được thoát đến \\ x [A-F0-9] [A-F0-9].
Gọi như vậy:
$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));
}
?>
Tôi đã giải quyết vấn đề cho UTF8 bằng cách sử dụng https://github.com/neitanod/forceutf8
use ForceUTF8\Encoding;
$string = Encoding::fixUTF8($string);
Regex vào câu trả lời được chọn không thành công cho Unicode: 0x1d (với php 7.4)
một giải pháp:
<?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;