Я думаю, мені потрібно видалити знаки 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 і видаляє його.
Ви потрапили в машину часу з гарячою ванною, і ви знову у вісімдесятих. Якщо у вас є форма 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 є досить ефективним, але якщо ви робите цю операцію багато, ви можете створити масив символів, які ви хочете видалити, і використовувати str_replace, як зазначено нижче mgutt, наприклад
//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-8kb, str_replace мав граничне ребро.
Я вважав це цікавим результатом, тому включив його сюди. Важливо не брати цей результат, а використовувати його, щоб визначити, який метод використовувати, а порівняти власні дані, а потім прийняти рішення.
У багатьох інших відповідях тут не враховуються символи Unicode (наприклад, öäüßйȝîûηы ე மி ᚉ ⠛). У цьому випадку ви можете використовувати наступне:
$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, ви можете:
Фільтр символів ASCII нижче 32
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
Фільтруйте символи ASCII вище 127
$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-адрес тощо. Отже, безліч варіантів санітарії (викресліть дані) та навіть перевірки (поверніть помилкове, якщо не дійсне, а не мовчки знімати).
Санітація: http://php.net/manual/en/filter.filters.sanitize.php
Перевірка: http://php.net/manual/en/filter.filters.validate.php
Однак проблема все ще є, що FILTER_FLAG_STRIP_LOW викреслить нову лінію та повернення каретки, які для текстових областей є повністю дійсними символами ... тому деякі відповіді Regex, я думаю, все ще потрібні часом, наприклад, після перегляду цього нитка, я планую це зробити для textareas:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
Це здається більш читабельним, ніж кількість регулярних виразів, які викреслюються за числовим діапазоном.
ви можете використовувати класи символів
/[[:cntrl:]]+/
це простіше:
$ 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);
тому що всі персонажі смайлів
Ви можете використовувати звичайний експрес, щоб видалити все, крім тих символів, які ви хочете зберегти:
$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);
Замінює все, що не є (^) літерами AZ або az, цифрами 0-9, пробіл, підкреслення, hypen, плюс і амперсанд - нічим (тобто видаліть його).
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);
Цей код видаляє будь-які символи в шістнадцятковій діапазоні 0-31 та 128-255, залишаючи в отриманій рядку лише шістнадцяткові символи 32-127, які я називаю в цьому прикладі $.
Відповідь @PaulDixon це абсолютно неправильно , тому що вона видаляє друкуються розширені символи ASCII 128-255!була частково виправлена. Я не знаю, чому він все ще хоче видалити 128-255 з 127 символів 7-бітного набору ASCII, оскільки він не має розширених символів ASCII.
Нарешті, важливо було не видаляти 128-255, тому що, наприклад chr(128)
( \x80
) є знак євро у 8-бітовому ASCII та багато шрифтів UTF-8 у Windows, виводять знак євро та Android щодо мого власного тесту.
І це вб'є багато символів UTF-8, якщо ви видалите символи ASCII 128-255 з рядка UTF-8 (можливо, початкові байти багатобайтового символу UTF-8). Тож не робіть цього! Вони є повністю легальними символами у всіх використовуваних в даний час файлових системах. Єдиний зарезервований діапазон - 0-31 .
Натомість використовуйте це, щоб видалити символи 0-31 та 127, які не можна друкувати:
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Він працює в ASCII і UTF-8, оскільки обидва мають однаковий діапазон набору керування .
Швидкий slower¹ альтернатива без використання регулярних виразів:
$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 та перевірена власноруч.
Позначений анвесер ідеальний, але йому не вистачає символу 127 (DEL), який також є символом, який не можна роздрукувати
моя відповідь буде
$string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string);
"cedivad" вирішив для мене це питання наполегливим результатом шведських знаків ÅÄÖ.
$text = preg_replace( '/[^\p{L}\s]/u', '', $text );
Дякую!
Для всіх, хто все ще шукає, як це зробити, не видаляючи символи, що не друкуються, а скоріше уникаючи їх, я зробив це, щоб допомогти. Сміливо вдосконалюйте його! Символи переходять у \\ 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));
}
?>
Я вирішив проблему для UTF8 за допомогою https://github.com/neitanod/forceutf8
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;
з: UTF 8 String видаліть усі невидимі символи, крім нового рядка