0-31 ve 127 karakterlerini kaldırmam gerektiğini düşünüyorum,
Bunu verimli bir şekilde yapmak için bir fonksiyon veya kod parçası var mı?
0-31 ve 127 karakterlerini kaldırmam gerektiğini düşünüyorum,
Bunu verimli bir şekilde yapmak için bir fonksiyon veya kod parçası var mı?
Yanıtlar:
Tardis'iniz 1963'te indi ve sadece 7 bitlik yazdırılabilir ASCII karakterlerini istiyorsanız, 0-31 ve 127-255 arasındaki her şeyi şununla sökebilirsiniz:
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
0-31, 127-255 aralığındaki herhangi bir şeyle eşleşir ve kaldırır.
Bir Hot Tub Zaman Makinesine düştünüz ve seksenlere geri döndünüz. Bir çeşit 8 bit ASCII'niz varsa, karakterleri 128-255 aralığında tutmak isteyebilirsiniz. Kolay ayar - sadece 0-31 ve 127'yi arayın
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Ah, 21. yüzyıla tekrar hoş geldiniz. UTF-8 kodlu bir dizeniz varsa, /u
değiştirici normal ifadede kullanılabilir
$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
Bu sadece 0-31 ve 127'yi kaldırır. ASCII ve UTF-8'de çalışır, çünkü her ikisi de aynı kontrol seti aralığını paylaşır (aşağıdaki mgutt tarafından belirtildiği gibi). Kesinlikle, bu /u
değiştirici olmadan çalışır . Ancak diğer karakterleri kaldırmak isterseniz hayatı kolaylaştırır ...
Unicode ile uğraşıyorsanız, potansiyel olarak birçok baskı dışı öğe var , ancak basit bir tane düşünelim: NO-BREAK SPACE (U + 00A0)
UTF-8 dizgisinde bu olarak kodlanır 0xC2A0
. Bu belirli diziyi /u
arayabilir ve kaldırabilirsiniz, ancak değiştirici yerinde \xA0
iken, karakter sınıfına ekleyebilirsiniz :
$string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string);
preg_replace oldukça verimlidir, ancak bu işlemi çok yapıyorsanız, kaldırmak istediğiniz karakter dizisini oluşturabilir ve aşağıdaki mgutt tarafından belirtildiği gibi str_replace kullanabilirsiniz.
//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);
Sezgisel olarak, bu hızlı olacak gibi görünüyor, ama her zaman böyle değil, kesinlikle bir şey kaydedip kaydetmediğini görmek için kesinlikle kıyaslamalısınız. Rasgele veriler ile çeşitli dize uzunlukları arasında bazı kriterler yaptım ve bu desen php 7.0.12 kullanılarak ortaya çıktı
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
Zamanlamalar 10000 yineleme içindir, ancak daha ilginç olan göreceli farklılıklardır. 512 karaktere kadar, preg_replace alway galibiyeti görüyordum. 1-8kb aralığında, str_replace kenar boşluğuna sahipti.
İlginç bir sonuç olduğunu düşündüm, bu yüzden buraya dahil ettim. Önemli olan bu sonucu almak ve hangi yöntemi kullanacağına karar vermek değil, kendi verilerinizle kıyaslamak ve sonra karar vermektir.
Buradaki diğer cevapların çoğu unicode karakterleri dikkate almaz (örn. Öäüßйȝîûηы ე மி ᚉ ⠛). Bu durumda aşağıdakileri kullanabilirsiniz:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string);
\x80-\x9F
Aralıkta teknik olarak kontrol karakterleri olan garip bir karakter sınıfı var ( 7 bitlik ASCII karakter aralığının hemen üstünde), ancak zaman içinde yazdırılabilir karakterler için kötüye kullanıldı. Bunlarla ilgili herhangi bir sorununuz yoksa, şunları kullanabilirsiniz:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $string);
Satır beslemelerini, satır başlarını, sekmeleri, kırılmayan boşlukları ve yumuşak kısa çizgileri de şeritlemek istiyorsanız, şunları kullanabilirsiniz:
$string = preg_replace('/[\x00-\x1F\x7F-\xA0\xAD]/u', '', $string);
Yukarıdaki örnekler için tek tırnak kullanmanız gerektiğini unutmayın .
Temel yazdırılabilir ASCII karakterleri hariç her şeyi soymak istiyorsanız (yukarıdaki tüm örnek karakterler çıkarılır) kullanabilirsiniz:
$string = preg_replace( '/[^[:print:]]/', '',$string);
Referans için bkz. Http://www.fileformat.info/info/charset/UTF-8/list.htm
'/[\x00-\x1F\x80-\xC0]/u'
onları sağlam bırakır; aynı zamanda bölme (F7) ve çarpma (D7) işareti.
\x7F-\x9F
?
PHP 5.2 ile başlayarak, orada atmak istiyorum diye düşündüm herhangi bir söz görmedim filter_var erişim var. <32 ve> 127 yazdırılamayan karakterleri ayırmak için filter_var kullanmak için şunları yapabilirsiniz:
32'nin altındaki ASCII karakterlerine filtre uygulama
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
127'nin üzerindeki ASCII karakterlerine filtre uygulama
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH);
Her ikisini de soyun:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
Ayrıca, yüksek sıyrılarak düşük karakterleri (satırsonu, sekme vb.) Html ile kodlayabilirsiniz:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_LOW|FILTER_FLAG_STRIP_HIGH);
HTML'yi sıyırma, e-postaları ve URL'leri sterilize etme, vb. Seçenekleri de vardır.
Sterilizasyon: http://php.net/manual/en/filter.filters.sanitize.php
Doğrulama: http://php.net/manual/en/filter.filters.validate.php
Bununla birlikte, hala bir sorun var, FILTER_FLAG_STRIP_LOW bir textarea için tamamen geçerli karakterler olan satırsonu ve satır başı döndürmelerini çıkaracaktır ... iplik, bunu textareas için yapmayı planlıyorum:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
Bu, sayısal aralıkla çıkarılan bir dizi normalden daha okunabilir görünüyor.
karakter sınıflarını kullanabilirsiniz
/[[:cntrl:]]+/
bu daha basit:
$ string = preg_replace ('/ [^ [: cntrl:]] /', '', $ string);
Tüm çözümler kısmen çalışıyor ve aşağıda bile muhtemelen tüm vakaları kapsamıyor. Benim sorunum bir utf8 mysql tabloya bir dize eklemek çalışıyordu. Dize (ve baytları) utf8 ile uyumludur, ancak birkaç kötü diziye sahiptir. Çoğunun kontrol veya biçimlendirme olduğunu varsayıyorum.
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;
}
Sorunu daha da kötüleştirmek için, tablodan sunucuya, içeriğin bağlantısına ve oluşturulmasına, burada biraz bahsedildiği gibi
$s = preg_replace('/(\xF0\x9F[\x00-\xFF][\x00-\xFF])/', ' ', $s);
tüm emoji karakterleri mysql berbat olduğu için eklemek zorunda kaldım
Saklamak istediğiniz karakterlerin dışındaki her şeyi kaldırmak için normal bir ifade kullanabilirsiniz:
$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);
AZ veya az harfleri (^), 0-9 sayıları, boşluk, alt çizgi, hiper, artı ve ve işareti olmayan her şeyi değiştirir (yani kaldırın).
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
Bu , yeni satır karakterlerini bırakarak tüm kontrol karakterlerini ( http://uk.php.net/manual/en/regexp.reference.unicode.php ) kaldıracaktır \n
. Deneyimlerime göre, kontrol karakterleri en sık yazdırma sorunlarına neden olan karakterlerdir.
/u
UTF-8 karakterleri için ekledim . İlk bölümün ne yaptığını açıklar (?!\n)
mısınız?
ASCII olmayan tüm karakterleri giriş dizesinden çıkarmak için
$result = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
Bu kod, bu örnekte $ sonuç olarak adlandırdığım sonuç dizesinde yalnızca 32-127 hex karakterlerini bırakarak onaltılık aralıklarda 0-31 ve 128-255 karakterleri kaldırır.
@PaulDixon cevabı ise tamamen yanlış çünkü, yazdırılabilir kaldırır genişletilmiş ASCII karakterleri 128-255! kısmen düzeltildi. Neden hala genişletilmiş ASCII karakterleri olmadığı için 127 karakterlik 7 bitlik ASCII setinden 128-255'i silmek istediğini bilmiyorum.
Ancak son olarak 128-255'i silmemek önemliydi çünkü örneğin chr(128)
( \x80
) 8-bit ASCII'de euro işareti ve Windows'taki birçok UTF-8 yazı tipi kendi testimle ilgili bir euro işareti ve Android gösteriyor.
Ve ASCII karakterlerini 128-255 bir UTF-8 dizesinden (muhtemelen çok baytlık bir UTF-8 karakterinin başlangıç baytları) kaldırırsanız, birçok UTF-8 karakterini öldürür. Öyleyse yapma! Şu anda kullanılan tüm dosya sistemlerinde tamamen yasal karakterlerdir. Tek ayrılmış aralık 0-31'dir .
Bunun yerine, yazdırılamayan 0-31 ve 127 karakterlerini silmek için bunu kullanın:
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Her ikisi de aynı kontrol seti aralığını paylaştığı için ASCII ve UTF-8'de çalışır .
En hızlı normal ifadeler kullanmadan slower¹ alternatif:
$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);
Eğer tüm boş karakterleri tutmak istiyorsanız \t
, \n
ve \r
daha sonra kaldırmak chr(9)
, chr(10)
ve chr(13)
bu listeden. Not: Her zamanki boşluk chr(32)
böylece sonuçta kalır. chr(160)
Sorunlara neden olabileceğinden kırılmayan alanı kaldırmak isteyip istemediğinize kendiniz karar verin .
@ @PaulDixon tarafından test edildi ve kendim doğruladım.
İşaretli anwser mükemmel, ancak yazdırılamayan bir karakter olan 127 (DEL) karakterini de kaçırıyor
cevabım olurdu
$string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string);
"cedivad", İsveçli chars ÅÄÖ'nin kalıcı sonucu ile benim için sorunu çözdü.
$text = preg_replace( '/[^\p{L}\s]/u', '', $text );
Teşekkürler!
Yazdırılamayan karakterleri kaldırmadan bunu nasıl yapacağını arayan, ancak onlardan kaçan herkes için, bunu yardımcı olmak için yaptım. Geliştirmek için çekinmeyin! Karakterler \\ x [A-F0-9] [A-F0-9] karakterinden kaçıyor.
Şöyle arayın:
$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 kullanarak UTF8 için sorunu çözdüm
use ForceUTF8\Encoding;
$string = Encoding::fixUTF8($string);
Seçilen cevaba yapılan normal ifade Unicode için başarısız oldu: 0x1d (php 7.4 ile)
bir çözüm:
<?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 Dize newline hariç tüm görünmez karakterleri kaldır