Remova o caractere não ascii da string


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

e eu preciso remover todos os caracteres não ascii da string,

significa str contém apenas "INFO] (Higashikurume)";

Respostas:


234

ASCII está no intervalo de 0 a 127, então:

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

8
@AlexanderMills Pesquise uma tabela ascii - você pode ver que apenas os caracteres com valor de zero a 127 são válidos. (0x7F é 127 em hexadecimal). Este código corresponde a todos os caracteres que não estão na faixa ascii e os remove.
Zaffy

obrigado por compartilhar. Você se importaria de explicar como funciona o \ x7F? Obrigado novamente.
eyyo de

1
@eyyo IIt representa o último caractere ascii. Eu não posso te dar uma explicação completa em um comentário como este. É chamada de sequência de escape hexadecimal, se você pesquisar por ela, certamente encontrará toneladas de informações sobre ela.
Zaffy

32

Também pode ser feito com uma afirmação positiva de remoção, como esta:

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

Isso usa Unicode. Em Javascript, ao expressar unicode para uma expressão regular, os caracteres são especificados com a sequência de escape, \u{xxxx}mas também o sinalizador 'u'deve apresentar; observe que a regex tem sinalizadores 'gu'.

Chamei isso de "afirmação positiva de remoção" no sentido de que uma afirmação "positiva" expressa quais caracteres remover, enquanto uma afirmação "negativa" expressa quais letras não remover. Em muitos contextos, a afirmação negativa, conforme declarada nas respostas anteriores, pode ser mais sugestiva para o leitor. O circunflexo " ^" diz "não" e o intervalo \x00-\x7Fdiz "ascii", então os dois juntos dizem "não ascii".

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

Essa é uma ótima solução para falantes de inglês que se preocupam apenas com o idioma inglês, e também é uma boa resposta para a pergunta original. Mas, em um contexto mais geral, nem sempre se pode aceitar o viés cultural de supor que "todos os não-ascii são ruins". Para contextos onde não ASCII é usado, mas ocasionalmente precisa ser removido, a afirmação positiva do Unicode é um ajuste melhor.

Uma boa indicação de que caracteres de largura zero e não imprimíveis estão embutidos em uma string é quando a propriedade "length" da string é positiva (diferente de zero), mas parece (isto é, imprime como) uma string vazia. Por exemplo, isso apareceu no depurador do Chrome, para uma variável chamada "textContent":

> textContent
""
> textContent.length
7

Isso me levou a querer ver o que havia naquela string.

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

Essa sequência de bytes parece estar na família de alguns caracteres Unicode que são inseridos por processadores de texto em documentos e, em seguida, encontram seu caminho em campos de dados. Mais comumente, esses símbolos ocorrem no final de um documento. O espaço de largura zero "%E2%80%8B"pode ser inserido pelo 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

Algumas referências sobre:

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

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

Observe que, embora a codificação do caractere incorporado seja UTF-8, a codificação na expressão regular não é. Embora o caractere seja incorporado na string como três bytes (no meu caso) de UTF-8, as instruções na expressão regular devem usar o Unicode de dois bytes. Na verdade, o UTF-8 pode ter até quatro bytes de comprimento; é menos compacto do que Unicode porque usa o bit (ou bits) alto para escapar da codificação ascii padrão. Isso é explicado aqui:

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


3
textContent = textContent.replace(/[\u{0080}-\u{FFFF}]/gu,"");não funciona no IE (pelo menos no IE 11). Ele falha com o erro: SCRIPT5021 : intervalo inválido no conjunto de caracteres
Andrey Sorich

14

Você pode usar o seguinte regex para substituir caracteres não ASCII

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

No entanto, observe que espaços, dois-pontos e vírgulas são todos ASCII válidos, então o resultado será

> str
"INFO] :, , ,  (Higashikurume)"

Não sou muito bom com regex, mas sei que o método .replace () pega o que você deseja substituir e substitui o segundo parâmetro como .replace ('substituir este texto', 'por este texto'). Então, qual parte disso diz para fazer o oposto e deixar os caracteres ASCII e remover os outros. Obrigado.
NicoM

2
Caracteres @NicoM []significam qualquer caractere, mas [^]significam o oposto - correspondem a qualquer caractere que não esteja entre colchetes.
Zaffy

11

Nenhuma dessas respostas lida corretamente com tabulações, novas linhas, retornos de carro e algumas não lidam com ASCII estendido e Unicode. Isso irá MANTER tabulações e novas linhas, mas removerá caracteres de controle e qualquer coisa fora do conjunto ASCII. Clique no botão "Executar este snippet de código" para testar. Há algum javascript novo chegando, então no futuro (2020+?) Você pode ter que fazer, \u{FFFFF}mas ainda não

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


é um bom regex, mas também remove acentos e emojis. Não tenho certeza de como melhorar este regex para cobrir esses casos.
Julio Vedovatto,

Para quem procura uma possível solução para remover Angular window.atob e DOMSanitizer.bypassSecurity ... caracteres inválidos (seja% 80, \ uFFFF ou espaços em branco inexplicáveis) ao converter para base64, esta é uma solução de trabalho
B. León

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.