답변:
Tardis가 1963 년에 출시되었고 7 비트 인쇄 가능한 ASCII 문자를 원한다면 다음과 같이 0-31 및 127-255의 모든 항목을 제거 할 수 있습니다.
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
0-31, 127-255 범위의 모든 항목과 일치하고 제거합니다.
당신은 핫 터브 타임머신에 빠졌고 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
수정 자 없이 작동합니다 . 그러나 다른 문자를 제거하려면 인생을 더 쉽게 만듭니다 ...
유니 코드를 다루는 경우 비 인쇄 요소가 많을 수 있지만 간단한 요소를 고려하십시오 .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-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을 제거하려면 다음을 수행하십시오.
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는 줄 바꿈과 캐리지 리턴을 제거하여 텍스트 영역의 경우 완전히 유효한 문자를 제거한다는 문제가 여전히 있습니다. 따라서 정규 표현식 답변 중 일부는 때때로 검토해야합니다. 스레드, 나는 텍스트 영역에 대해 이것을 할 계획이다 :
$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의를 엉망으로했다
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
이것은 개행 문자를 남기는 모든 제어 문자 ( http://uk.php.net/manual/en/regexp.reference.unicode.php )를 제거합니다 \n
. 내 경험상 컨트롤 문자는 인쇄 문제를 가장 자주 일으키는 문자입니다.
/u
UTF-8 문자 에만 추가했습니다 . 첫 번째 부분 (?!\n)
이 무엇인지 설명해 주 시겠습니까?
@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에서 작동 모두 공유하기 때문에 동일한 제어 설정 범위 .
빠른 정규 표현식을 사용하지 않고 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);
인쇄 할 수없는 문자를 제거하지 않고 이스케이프 처리하지 않고이 작업을 수행하는 방법을 계속 찾고있는 사람이라면 도움이 될 것입니다. 자유롭게 개선하십시오! 문자는 \\ 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);
선택한 답변에 대한 정규식이 유니 코드에 대해 실패합니다 : 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;