2016-08-25 24 views
13

Rozważmy następujący Unicode ciężki wyrażenia regularnego (emotikonów stojąc na non-ASCII i extra-BMP znaków):Kolejność logiczną OR w ES6/Unicode wyrażenia regularnego w Chrome ✗ vs Firefox ✓

''.match(/||/ug) 

Firefox zwraca [ "", "", "", "", "", "" ].

Chrome 52.0.2743.116 i węzeł 6.4.0 oba zwracają null! Nie wydaje mi się, żebym dbał o to, czy wstawię ciąg znaków do zmiennej i czynię str.match(…), czy też nie zbuduję obiektu RegExp przez new RegExp('||', 'gu').

(Chrome jest ok tylko z Oring dwa sekwencje: ''.match(/|/ug) jest ok Jest to również ok z non-Unicode. 'aakkzzkkaa'.match(/aa|kk|zz/ug) działa.)

robię coś źle? Czy to błąd przeglądarki Chrome? ECMAScript compatibility table mówi, że powinienem być w porządku z wyrażeń regularnych Unicode.

(PS:..? Trzy emotikonów użyta w tym przykładzie są tylko stand-ins W mojej aplikacji, będą arbitralne, lecz odrębne ciągi Ale zastanawiam się, czy fakt, że ''.match(/[]/ug) działa w Chrome jest istotne)

+0

Może jestem konserwatywny, ale to byłoby łatwiejsze do odczytania z 'foo',' bar' i 'baz' lub' A', 'B' i' C'. Plus wiele czcionek nadal nie robi wszystkich emotikonów, więc jeśli komuś brakuje dwóch z nich, zobaczą je jako kwadrat - lub co gorsza wszystkie trzy. –

+0

@CaptainMan na świecie mówi wieloma językami, z których wiele jest napisanych za pomocą znaków spoza ASCII lub (gasp!). Używam emoji jako standinu dla tych postaci. (Również wskazuję we wpisie, że ten sam przykład działa z ASCII, więc jest to problem z Unicode.) Aktualizowanie tytułu w celu podkreślenia Unicode. –

+0

Teraz widzę, że część punktu dotyczyła unikodu (początkowo go brakowało). Nadal uważam, że więcej "waniliowych" znaków unicode byłoby lepszych niż emoji. –

Odpowiedz

3

Bez flagi u, twoje wyrażenie regularne działa, i to nic dziwnego, ponieważ w trybie BMP (= nie "u") porównuje 16-bitowe "jednostki" z 16-bitowymi "jednostkami", to jest zastępczą sparować z inną zastępczą parą.

Zachowanie w trybie „U” (który ma na celu porównanie codepoints a nie jednostki) wygląda rzeczywiście jak robaka Chrome, w międzyczasie można ująć każdą alternatywę w grupie, co wydaje się działać prawidłowo:

m = ''.match(/()|()|()/ug) 
 
console.log(m) 
 

 
// note that the groups must be capturing! 
 
// this doesn't work: 
 

 
m = ''.match(/(?:)|(?:)|(?:)/ug) 
 
console.log(m)

A oto szybkie dowód, że ponad dwie alternatywy SMP są łamane w trybie u:

// insert a whatever range 
 
// from https://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane 
 
var range = '11300-1137F'; 
 

 
range = range.split('-').map(x => parseInt(x, 16)) 
 

 
var chars = []; 
 
for (var i = range[0]; i <= range[1]; i++) { 
 
    chars.push(String.fromCodePoint(i)) 
 
} 
 

 
var str = chars.join(''); 
 

 
while(chars.length) { 
 
    var re = new RegExp(chars.join('|'), 'u') 
 
    if(str.match(re)) 
 
     console.log(chars.length, re); 
 
    chars.pop(); 
 
}

W Chrome rejestruje tylko dwa ostatnie regexes (2 i 1 alts).

2

bez "u" FLAG to ma również pracować w Chrome (52.0.2743.116) dla mnie

u FLAG również wydaje się być uszkodzony

chyba użyć mnożnika ''.match(/|{2}|/g) -> null {1} i {1,} wydaje się działać, zakładam, że zostały przetłumaczone na? i +. Zakładam, że bez "u" -flag {2} jest interpretowany jako \ud83c\udf66{2}, co tłumaczyłoby to zachowanie.

Właśnie testowany z (?:){2} wydaje się działać poprawnie. Przypuszczam, że potwierdza to moje założenie co do mnożnika.

tutaj na szybkie ustalenie, że:

//a utility I usually have in my codes 
var replace = (pattern, replacement) => value => String(value).replace(pattern, replacement); 

var fixRegexSource = replace(
    /[\ud800-\udbff][\udc00-\udfff]/g, 
    //"(?:$&)" //not sure wether this might still be buggy 
    //that's why I convert it into the unicode-syntax, 
    //this can't be misinterpreted 
    c => `(?:\\u${c.charCodeAt(0).toString(16)}\\u${c.charCodeAt(1).toString(16)})` 
); 

var fixRegex = regex => new RegExp(
    fixRegexSource(regex.source), 
    regex.flags.replace("u", "") 
); 

sry, nie wymyślić lepszych funkcji nazw