Supprimer le caractère non-ascii dans la chaîne

89
var str="INFO] :谷���新道, ひば���ヶ丘2丁���, ひばりヶ���, 東久留米市 (Higashikurume)";

et je dois supprimer tous les caractères non-ascii de la chaîne,

signifie que str ne contient que "INFO] (Higashikurume)";

Dev
la source

Réponses:

229

ASCII est compris entre 0 et 127, donc:

str.replace(/[^\x00-\x7F]/g, "");
Zaffy
la source
8
@AlexanderMills Recherchez une table ascii - vous pouvez voir que seuls les caractères dont la valeur est comprise entre zéro et 127 sont valides. (0x7F est 127 en hexadécimal). Ce code correspond à tous les caractères qui ne sont pas dans la plage ascii et les supprime.
Zaffy
31

Cela peut également être fait avec une affirmation positive de suppression, comme ceci:

textContent = textContent.replace(/[\u{0080}-\u{FFFF}]/gu,"");

Cela utilise unicode. En Javascript, lors de l'expression d'unicode pour une expression régulière, les caractères sont spécifiés avec la séquence d'échappement \u{xxxx}mais aussi le drapeau 'u'doit être présent; notez que l'expression régulière a des indicateurs 'gu'.

J'ai appelé cela une "assertion positive de suppression" dans le sens où une assertion "positive" exprime les caractères à supprimer, tandis qu'une assertion "négative" exprime les lettres à ne pas supprimer. Dans de nombreux contextes, l'assertion négative, comme indiqué dans les réponses précédentes, pourrait être plus suggestive pour le lecteur. Le circonflexe " ^" dit "non" et la plage \x00-\x7Fdit "ascii", donc les deux ensemble disent "pas ascii".

textContent = textContent.replace(/[^\x00-\x7F]/g,"");

C'est une excellente solution pour les anglophones qui ne se soucient que de la langue anglaise, et c'est aussi une bonne réponse à la question originale. Mais dans un contexte plus général, on ne peut pas toujours accepter le biais culturel consistant à supposer que «tout non-ascii est mauvais». Pour les contextes où non-ascii est utilisé, mais doit parfois être supprimé, l'affirmation positive d'Unicode convient mieux.

Une bonne indication que des caractères de largeur nulle et non imprimables sont incorporés dans une chaîne est lorsque la propriété "length" de la chaîne est positive (différente de zéro), mais ressemble (c'est-à-dire s'imprime comme) une chaîne vide. Par exemple, j'ai fait apparaître ceci dans le débogueur Chrome, pour une variable nommée "textContent":

> textContent
""
> textContent.length
7

Cela m'a incité à vouloir voir ce qu'il y avait dans cette chaîne.

> encodeURI(textContent)
"%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B%E2%80%8B"

Cette séquence d'octets semble faire partie de la famille de certains caractères Unicode qui sont insérés par les traitements de texte dans les documents, puis trouvent leur chemin dans les champs de données. Le plus souvent, ces symboles apparaissent à la fin d'un document. L'espace de largeur zéro "%E2%80%8B"peut être inséré par CK-Editor (CKEditor).

encodeURI()  UTF-8     Unicode  html     Meaning
-----------  --------  -------  -------  -------------------
"%E2%80%8B"  EC 80 8B  U 200B   ​  zero-width-space
"%E2%80%8E"  EC 80 8E  U 200E   ‎  left-to-right-mark
"%E2%80%8F"  EC 80 8F  U 200F   ‏  right-to-left-mark

Quelques références sur ceux-ci:

http://www.fileformat.info/info/unicode/char/200B/index.htm

https://en.wikipedia.org/wiki/Left-to-right_mark

Notez que bien que le codage du caractère incorporé soit UTF-8, le codage dans l'expression régulière ne l'est pas. Bien que le caractère soit incorporé dans la chaîne sous forme de trois octets (dans mon cas) de UTF-8, les instructions de l'expression régulière doivent utiliser l'Unicode à deux octets. En fait, UTF-8 peut durer jusqu'à quatre octets; il est moins compact qu'Unicode car il utilise le ou les bits hauts pour échapper au codage ascii standard. C'est expliqué ici:

https://en.wikipedia.org/wiki/UTF-8

IAM_AL_X
la source
3
textContent = textContent.replace(/[\u{0080}-\u{FFFF}]/gu,"");ne fonctionne pas dans IE (au moins IE 11). Il échoue avec l'erreur: SCRIPT5021 : plage non valide dans le jeu de caractères
Andrey Sorich
14

Vous pouvez utiliser l'expression régulière suivante pour remplacer les caractères non ASCII

str = str.replace(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, '')

Cependant, notez que les espaces, les deux points et les virgules sont tous ASCII valides, le résultat sera donc

> str
"INFO] :, , ,  (Higashikurume)"
Chris Taylor
la source
Je ne suis pas génial avec les regex mais je sais que la méthode .replace () prend la chose que vous voulez remplacer et remplace le deuxième paramètre comme .replace ('replace this text', 'with this text'). Alors, quelle partie de cela dit, faites le contraire et laissez les caractères ascii et supprimez les autres. Merci.
NicoM
2
@NicoM Les caractères []signifient n'importe quel caractère mais en [^]sens contraire - correspondent à n'importe quel caractère non entre crochets.
Zaffy
11

Aucune de ces réponses ne gère correctement les tabulations, les retours à la ligne, les retours chariot, et certaines ne gèrent pas l'ASCII étendu et l'unicode. Cela gardera les onglets et les nouvelles lignes, mais supprimera les caractères de contrôle et tout ce qui ne fait pas partie de l'ensemble ASCII. Cliquez sur le bouton "Exécuter cet extrait de code" pour tester. Il y a du nouveau javascript à venir, donc à l'avenir (2020+?) Vous devrez peut-être le faire, \u{FFFFF}mais pas encore

console.log("line 1\nline2 \n\ttabbed\nF̸̡̢͓̳̜̪̟̳̠̻̖͐̂̍̅̔̂͋͂͐l̸̢̹̣̤̙͚̱͓̖̹̻̣͇͗͂̃̈͝a̸̢̡̬͕͕̰̖͍̮̪̬̍̏̎̕͘ͅv̸̢̛̠̟̄̿i̵̮͌̑ǫ̶̖͓͎̝͈̰̹̫͚͓̠̜̓̈́̇̆̑͜ͅ".replace(/[\x00-\x08\x0E-\x1F\x7F-\uFFFF]/g, ''))

Jonathan
la source
c'est une bonne regex, mais elle supprime également les accents et les émojis. Je ne sais pas comment améliorer cette expression régulière pour couvrir ces cas.
Julio Vedovatto le
Pour ceux qui cherchent une solution possible à la suppression angulaire window.atob et DOMSanitizer.bypassSecurity ... caractères non valides (80% que ce soit, \ uFFFF ou inexpliqués espaces blancs) lors de la conversion à base64, c'est une solution de travail
B. León