J'imagine que j'ai besoin de supprimer les caractères 0-31 et 127,
Existe-t-il une fonction ou un morceau de code pour le faire efficacement?
J'imagine que j'ai besoin de supprimer les caractères 0-31 et 127,
Existe-t-il une fonction ou un morceau de code pour le faire efficacement?
Réponses:
Si votre Tardis vient d'atterrir en 1963 et que vous voulez juste les caractères ASCII imprimables 7 bits, vous pouvez tout extraire de 0-31 et 127-255 avec ceci:
$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);
Il correspond à tout ce qui se trouve dans la plage 0-31, 127-255 et le supprime.
Vous êtes tombé dans une machine à voyager dans le temps et vous êtes de retour dans les années quatre-vingt. Si vous avez une forme d'ASCII 8 bits, vous voudrez peut-être garder les caractères dans la plage 128-255. Un réglage facile - il suffit de rechercher 0-31 et 127
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Ah, bienvenue au 21e siècle. Si vous avez une chaîne encodée en UTF-8, le /u
modificateur peut être utilisé sur l'expression régulière
$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);
Cela supprime simplement 0-31 et 127. Cela fonctionne en ASCII et UTF-8 car les deux partagent la même plage de jeu de contrôle (comme indiqué par mgutt ci-dessous). Strictement parlant, cela fonctionnerait sans le /u
modificateur. Mais cela vous facilite la vie si vous souhaitez supprimer d'autres caractères ...
Si vous avez affaire à Unicode, il existe potentiellement de nombreux éléments non imprimables , mais considérons un élément simple: NO-BREAK SPACE (U + 00A0)
Dans une chaîne UTF-8, cela serait codé comme 0xC2A0
. Vous pouvez rechercher et supprimer cette séquence spécifique, mais avec le /u
modificateur en place, vous pouvez simplement ajouter \xA0
à la classe de caractères:
$string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string);
preg_replace est assez efficace, mais si vous faites beaucoup cette opération, vous pouvez créer un tableau de caractères que vous souhaitez supprimer, et utiliser str_replace comme indiqué par mgutt ci-dessous, par exemple
//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);
Intuitivement, cela semble être rapide, mais ce n'est pas toujours le cas, vous devez absolument vous comparer pour voir si cela vous permet d'économiser quelque chose. J'ai fait quelques tests sur une variété de longueurs de chaîne avec des données aléatoires, et ce modèle est apparu en utilisant 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
Les durées elles-mêmes sont pour 10000 itérations, mais ce qui est plus intéressant, ce sont les différences relatives. Jusqu'à 512 caractères, je voyais toujours preg_replace gagner. Dans la plage de 1 à 8 Ko, str_replace avait un bord marginal.
J'ai trouvé que c'était un résultat intéressant, alors incluez-le ici. L'important n'est pas de prendre ce résultat et de l'utiliser pour décider de la méthode à utiliser, mais de le comparer à vos propres données, puis de décider.
La plupart des autres réponses ici ne prennent pas en compte les caractères unicode (par exemple öäüßйȝîûηы ე மி ᚉ ⠛). Dans ce cas, vous pouvez utiliser les éléments suivants:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/u', '', $string);
Il y a une classe étrange de caractères dans la plage \x80-\x9F
(juste au-dessus de la plage de caractères ASCII 7 bits) qui sont techniquement des caractères de contrôle, mais avec le temps, elles ont été mal utilisées pour des caractères imprimables. Si vous n'avez aucun problème avec ceux-ci, vous pouvez utiliser:
$string = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $string);
Si vous souhaitez également supprimer les sauts de ligne, les retours chariot, les tabulations, les espaces insécables et les tirets souples, vous pouvez utiliser:
$string = preg_replace('/[\x00-\x1F\x7F-\xA0\xAD]/u', '', $string);
Notez que vous devez utiliser des guillemets simples pour les exemples ci-dessus.
Si vous souhaitez tout supprimer sauf les caractères ASCII imprimables de base (tous les exemples de caractères ci-dessus seront supprimés), vous pouvez utiliser:
$string = preg_replace( '/[^[:print:]]/', '',$string);
Pour référence, voir http://www.fileformat.info/info/charset/UTF-8/list.htm
'/[\x00-\x1F\x80-\xC0]/u'
les laisse intacts; mais aussi le signe de division (F7) et de multiplication (D7).
\x7F-\x9F
?
À partir de PHP 5.2, nous avons également accès à filter_var, dont je n'ai vu aucune mention, alors j'ai pensé que je le jetterais là-bas. Pour utiliser filter_var pour supprimer les caractères non imprimables <32 et> 127, vous pouvez faire:
Filtrez les caractères ASCII inférieurs à 32
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
Filtrer les caractères ASCII au-dessus de 127
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH);
Dénudez les deux:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
Vous pouvez également encoder en HTML des caractères bas (nouvelle ligne, tabulation, etc.) tout en décapant haut:
$string = filter_var($input, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_LOW|FILTER_FLAG_STRIP_HIGH);
Il existe également des options pour supprimer le HTML, nettoyer les e-mails et les URL, etc. Donc, de nombreuses options pour le nettoyage (supprimer les données) et même la validation (retourner false si non valide plutôt que supprimer silencieusement).
Désinfection: http://php.net/manual/en/filter.filters.sanitize.php
Validation: http://php.net/manual/en/filter.filters.validate.php
Cependant, il y a toujours le problème, que le FILTER_FLAG_STRIP_LOW supprime les retours à la ligne et les retours chariot, qui pour une zone de texte sont des caractères complètement valides ... donc certaines des réponses Regex, je suppose, sont encore nécessaires parfois, par exemple après avoir examiné ceci thread, je prévois de le faire pour les zones de texte:
$string = preg_replace( '/[^[:print:]\r\n]/', '',$input);
Cela semble plus lisible qu'un certain nombre de regexes supprimées par plage numérique.
vous pouvez utiliser des classes de caractères
/[[:cntrl:]]+/
c'est plus simple:
$ string = preg_replace ('/ [^ [: cntrl:]] /', '', $ string);
Toutes les solutions fonctionnent partiellement, et même ci-dessous ne couvre probablement pas tous les cas. Mon problème était d'essayer d'insérer une chaîne dans une table mysql utf8. La chaîne (et ses octets) était conforme à utf8, mais avait plusieurs mauvaises séquences. Je suppose que la plupart d'entre eux étaient du contrôle ou du formatage.
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;
}
Pour aggraver encore le problème, il y a la table contre le serveur contre la connexion contre le rendu du contenu, comme on en parle un peu ici
$s = preg_replace('/(\xF0\x9F[\x00-\xFF][\x00-\xFF])/', ' ', $s);
parce que tous les personnages emoji gâchaient mysql
Ma version compatible UTF-8:
preg_replace('/[^\p{L}\s]/u','',$value);
Vous pouvez utiliser un express régulier pour tout supprimer à l'exception des caractères que vous souhaitez conserver:
$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);
Remplace tout ce qui n'est pas (^) les lettres AZ ou az, les chiffres 0-9, l'espace, le trait de soulignement, l'hypen, le plus et l'esperluette - par rien (c'est-à-dire supprimez-le).
preg_replace('/(?!\n)[\p{Cc}]/', '', $response);
Cela supprimera tous les caractères de contrôle ( http://uk.php.net/manual/en/regexp.reference.unicode.php ) laissant les \n
caractères de nouvelle ligne. D'après mon expérience, les caractères de contrôle sont ceux qui causent le plus souvent les problèmes d'impression.
/u
pour les caractères UTF-8. Pouvez-vous expliquer ce que fait la première partie (?!\n)
?
Pour supprimer tous les caractères non ASCII de la chaîne d'entrée
$result = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
Ce code supprime tous les caractères dans les plages hexadécimales 0-31 et 128-255, ne laissant que les caractères hexadécimaux 32-127 dans la chaîne résultante, que j'appelle $ result dans cet exemple.
La réponse de @PaulDixon est complètement fausse , car elle supprime les caractères ASCII étendus imprimables 128-255!a été partiellement corrigé. Je ne sais pas pourquoi il veut toujours supprimer 128-255 d'un ensemble ASCII 7 bits à 127 caractères car il n'a pas les caractères ASCII étendus.
Mais finalement, il était important de ne pas supprimer 128-255 car par exemple chr(128)
( \x80
) est le signe euro en ASCII 8 bits et de nombreuses polices UTF-8 dans Windows affichent un signe euro et Android concernant mon propre test.
Et cela tuera de nombreux caractères UTF-8 si vous supprimez les caractères ASCII 128-255 d'une chaîne UTF-8 (probablement les octets de départ d'un caractère UTF-8 multi-octets). Alors ne fais pas ça! Ce sont des caractères entièrement légaux dans tous les systèmes de fichiers actuellement utilisés. La seule plage réservée est 0-31 .
Utilisez plutôt ceci pour supprimer les caractères non imprimables 0-31 et 127:
$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);
Il fonctionne en ASCII et UTF-8 car les deux partagent la même plage de jeu de contrôle .
L' alternative la plus lente et la plus rapide sans utiliser d'expressions régulières:
$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);
Si vous voulez garder tous les caractères blancs \t
, \n
et \r
, puis retirer chr(9)
, chr(10)
et chr(13)
de cette liste. Remarque: L'espace blanc habituel est chr(32)
qu'il reste dans le résultat. Décidez vous-même si vous souhaitez supprimer l'espace insécable chr(160)
car cela peut causer des problèmes.
¹ Testé par @PaulDixon et vérifié par moi-même.
La réponse marquée est parfaite mais elle manque le caractère 127 (DEL) qui est également un caractère non imprimable
ma réponse serait
$string = preg_replace('/[\x00-\x1F\x7f-\xFF]/', '', $string);
"cedivad" a résolu le problème pour moi avec le résultat persistant des chars suédois ÅÄÖ.
$text = preg_replace( '/[^\p{L}\s]/u', '', $text );
Merci!
Pour tous ceux qui cherchent encore comment faire cela sans supprimer les caractères non imprimables, mais plutôt en les échappant, j'ai fait cela pour aider. N'hésitez pas à l'améliorer! Les caractères sont échappés vers \\ x [A-F0-9] [A-F0-9].
Appelez comme ça:
$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));
}
?>
J'ai résolu le problème pour UTF8 en utilisant https://github.com/neitanod/forceutf8
use ForceUTF8\Encoding;
$string = Encoding::fixUTF8($string);
Le regex dans la réponse sélectionnée échoue pour Unicode: 0x1d (avec php 7.4)
une solution:
<?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 supprime tous les caractères invisibles sauf le saut de ligne