Я думаю, мне нужно удалить символы 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
модификатора. Но это облегчает жизнь, если вы хотите удалить другие символы ...
Если вы имеете дело с Юникодом, потенциально существует много непечатаемых элементов , но давайте рассмотрим простой: 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 win. В диапазоне 1-8kb 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, вы можете сделать:
Фильтровать символы 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-адресов и т. Д. Итак, множество параметров для очистки (удаления данных) и даже проверки (возвращает false, если не допустимо, а не выполняет автоматическое удаление).
Санитарная обработка: 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);
Все решения работают частично, и даже ниже, вероятно, не охватывает все случаи. Моя проблема была в попытке вставить строку в таблицу mysql utf8. Строка (и ее байты) все соответствовали 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, пробелом, подчеркиванием, гипеном, плюсом и амперсандом - ничем (т.е. удаляет его).
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 в результирующей строке, которую я называю $ result в этом примере.
Ответ @PaulDixon это совершенно неправильно , потому что она удаляет печатаемые расширенные символы ASCII 128-255! был частично исправлен. Я не знаю, почему он все еще хочет удалить 128-255 из 127-битного набора ASCII из 127 символов, поскольку он не имеет расширенных символов 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, потому что оба используют один и тот же диапазон набора управления .
Самая быстрая медленная альтернатива без использования регулярных выражений:
$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);
«Седивад» решил проблему для меня с постоянным результатом шведских символов ÅÄÖ.
$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;
from: UTF 8 String удалить все невидимые символы, кроме новой строки