Usuń znak inny niż ASCII w ciągu

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

i muszę usunąć wszystkie znaki inne niż ASCII z ciągu,

oznacza, że ​​str zawiera tylko „INFO] (Higashikurume)”;

Dev
źródło

Odpowiedzi:

229

ASCII jest w zakresie od 0 do 127, więc:

str.replace(/[^\x00-\x7F]/g, "");
Zaffy
źródło
8
@AlexanderMills Wyszukaj tabelę ascii - możesz zobaczyć, że poprawne są tylko znaki o wartości od zera do 127. (0x7F to 127 w zapisie szesnastkowym). Ten kod dopasowuje wszystkie znaki spoza zakresu ascii i usuwa je.
Zaffy,
31

Można to również zrobić z pozytywnym potwierdzeniem usunięcia, na przykład:

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

To używa Unicode. W Javascript, podczas wyrażania Unicode w wyrażeniu regularnym, znaki są określane za pomocą sekwencji sterującej, \u{xxxx}ale 'u'musi również występować flaga ; zauważ, że wyrażenie regularne ma flagi 'gu'.

Nazwałem to „pozytywnym stwierdzeniem usunięcia” w tym sensie, że „pozytywne” stwierdzenie określa, które znaki należy usunąć, podczas gdy „negatywne” stwierdzenie określa, których liter nie należy usuwać. W wielu kontekstach twierdzenie negatywne, jak stwierdzono we wcześniejszych odpowiedziach, może być bardziej sugestywne dla czytelnika. Daszek „ ^” mówi „nie”, a zakres \x00-\x7Fmówi „ascii”, więc oba razem mówią „nie ascii”.

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

To świetne rozwiązanie dla osób mówiących po angielsku, którym zależy tylko na języku angielskim, a także dobra odpowiedź na oryginalne pytanie. Ale w bardziej ogólnym kontekście, nie zawsze można zaakceptować kulturowe nastawienie zakładające, że „wszystko, co nie jest ascii, jest złe”. W kontekstach, w których używane jest inne niż ASCII, ale czasami trzeba je usunąć, lepsze jest zapewnienie pozytywnego potwierdzenia Unicode.

Dobrą wskazówką, że znaki niedrukowalne o zerowej szerokości są osadzone w łańcuchu jest sytuacja, gdy właściwość „length” łańcucha jest dodatnia (różna od zera), ale wygląda jak (tj. Drukuje jako) pusty łańcuch. Na przykład pojawił się ten komunikat w debugerze Chrome dla zmiennej o nazwie „textContent”:

> textContent
""
> textContent.length
7

To skłoniło mnie do sprawdzenia, co jest w tym ciągu.

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

Wydaje się, że ta sekwencja bajtów należy do rodziny niektórych znaków Unicode, które są wstawiane przez edytory tekstu do dokumentów, a następnie trafiają do pól danych. Najczęściej te symbole pojawiają się na końcu dokumentu. Przestrzeń o zerowej szerokości "%E2%80%8B"może zostać wstawiona przez 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

Niektóre odniesienia na ten temat:

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

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

Należy zauważyć, że chociaż kodowanie osadzonego znaku to UTF-8, kodowanie w wyrażeniu regularnym nie. Chociaż znak jest osadzony w ciągu jako trzy bajty (w moim przypadku) UTF-8, instrukcje w wyrażeniu regularnym muszą używać dwubajtowego kodu Unicode. W rzeczywistości UTF-8 może mieć długość do czterech bajtów; jest mniej zwarty niż Unicode, ponieważ używa wysokiego bitu (lub bitów), aby uciec od standardowego kodowania ascii. To wyjaśniono tutaj:

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

IAM_AL_X
źródło
3
textContent = textContent.replace(/[\u{0080}-\u{FFFF}]/gu,"");nie działa w IE (przynajmniej IE 11). Niepowodzenie i błąd: SCRIPT5021 : Nieprawidłowy zakres w zestawie znaków
Andrey Sorich
14

Możesz użyć następującego wyrażenia regularnego, aby zamienić znaki spoza zestawu ASCII

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

Należy jednak pamiętać, że spacje, dwukropki i przecinki są poprawnymi znakami ASCII, więc wynik będzie

> str
"INFO] :, , ,  (Higashikurume)"
Chris Taylor
źródło
Nie jestem świetny z regexem, ale wiem, że metoda .replace () przyjmuje to, co chcesz zastąpić i zastępuje drugi parametr, taki jak .replace („zamień ten tekst”, „tym tekstem”). Więc co z tego mówi, zrób coś przeciwnego i zostaw znaki ascii i usuń pozostałe. Dzięki.
NicoM
2
@NicoM Znaki []oznaczają dowolny znak, ale [^]przeciwnie - dopasuj dowolny znak nie w nawiasach.
Zaffy,
10

Żadna z tych odpowiedzi nie obsługuje poprawnie tabulatorów, nowych linii, powrotu karetki, a niektóre nie obsługują rozszerzonego ASCII i Unicode. Pozwoli to ZACHOWAĆ tabulatory i znaki nowej linii, ale usunie znaki kontrolne i wszystko spoza zestawu ASCII. Kliknij przycisk „Uruchom ten fragment kodu”, aby przetestować. Pojawia się jakiś nowy javascript, więc w przyszłości (2020+?) Być może będziesz musiał to zrobić, \u{FFFFF}ale jeszcze nie

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

Jonathan
źródło
to dobre wyrażenie regularne, ale usuwa też akcenty i emotikony. Nie jestem pewien, jak ulepszyć to wyrażenie regularne, aby obejmowało te przypadki.
Julio Vedovatto
Dla każdego, kto szuka możliwego rozwiązania w celu usunięcia Angular window.atob i DOMSanitizer.bypassSecurity ... nieprawidłowych znaków (czy to% 80, \ uFFFF lub niewyjaśnionych spacji) podczas konwersji na base64, jest to działające rozwiązanie
B. León
9

Aby użyć ASCII z akcentami:

var str = str.replace(/[^\x00-\xFF]/g, "");
Eolia
źródło
Znakomity! Obsługuje wartości ascii powyżej 127, które inne odpowiedzi odrzucają.
user3413723
A co z tekstem alternatywnym z akcentami ... jak altcodeunicode.com/alt-codes-letter-e-with-accents ?
Stackedup