RegExp + limiti Word + caratteri unicode Javascript

Sto costruendo la ricerca e ho intenzione di utilizzare javascript autocomplete con esso. Vengo dalla Finlandia (lingua finlandese) quindi ho a che fare con alcuni personaggi speciali come ä, ö e å

Quando l’utente digita il testo nel campo di input di ricerca, cerco di abbinare il testo ai dati.

Ecco un semplice esempio che non funziona correttamente se l’utente digita, ad esempio “ää”. La stessa cosa con “äl”

var title = "this is simple string with finnish word tämä on ääkköstesti älkää ihmetelkö"; // Does not work var searchterm = "äl"; // does not work //var searchterm = "ää"; // Works //var searchterm = "wi"; if ( new RegExp("\\b"+searchterm, "gi").test(title) ) { $("#result").html("Match: ("+searchterm+"): "+title); } else { $("#result").html("nothing found with term: "+searchterm); } 

http://jsfiddle.net/7TsxB/

Quindi, come posso far sì che i caratteri ä, ö e å funzionino con regex javascript?

Penso che dovrei usare i codici unicode ma come dovrei farlo? I codici per questi caratteri sono: [\ u00C4, \ u00E4, \ u00C5, \ u00E5, \ u00D6, \ u00F6]

=> äÄåÅöÖ

Sembra che ci sia un problema con Regex e il limite della parola \b corrisponde all’inizio di una stringa con un carattere iniziale fuori dal normale intervallo di 256 byte.

Invece di usare \b , prova a usare (?:^|\\s)

 var title = "this is simple string with finnish word tämä on ääkköstesti älkää ihmetelkö"; // Does not work var searchterm = "äl"; // does not work //var searchterm = "ää"; // Works //var searchterm = "wi"; if ( new RegExp("(?:^|\\s)"+searchterm, "gi").test(title) ) { $("#result").html("Match: ("+searchterm+"): "+title); } else { $("#result").html("nothing found with term: "+searchterm); } 

Abbattersi:

(?: parentesi () forma un gruppo di cattura in Regex. Le parentesi iniziano con un punto interrogativo e due punti ?: formano un gruppo non catturante. Raggruppano semplicemente i termini insieme

^ il simbolo del caret corrisponde all’inizio di una stringa

| la barra è l’operatore “o”.

\s corrisponde allo spazio bianco (appare come \\s nella stringa perché dobbiamo sfuggire alla barra rovesciata)

) chiude il gruppo

Quindi, invece di usare \b , che corrisponde ai limiti delle parole e non funziona per i caratteri unicode, usiamo un gruppo non catturante che corrisponde all’inizio di uno spazio o uno spazio bianco.

La class di caratteri \b in JavaScript RegEx è davvero utile solo con la semplice codifica ASCII. \b è un codice di scelta rapida per il limite tra gli insiemi \w e \W o \w e l’inizio o la fine della stringa. Questi set di caratteri prendono in considerazione solo i caratteri “parola” ASCII, dove \w è uguale a [a-zA-Z0-9_] e \W è la negazione di quella class.

Questo rende le classi di caratteri RegEx largamente inutili per affrontare qualsiasi linguaggio reale.

\s dovrebbe funzionare per quello che vuoi fare, a condizione che i termini di ricerca siano solo delimitati da spazi bianchi.

questa domanda è vecchia, ma penso di aver trovato una soluzione migliore per il confine nelle espressioni regolari con lettere unicode. Usando XRegExp puoi implementare un limite \ b valido espandendo questo

 XRegExp('(?=^|$|[^\\p{L}])') 

il risultato è di oltre 4000 caratteri, ma sembra funzionare piuttosto bene.

Qualche spiegazione: (? =) È un lookahead di lunghezza zero che cerca un confine di inizio o fine o un carattere unicode senza lettere. Il pensiero più importante è il lookahead, perché il \ b non cattura nulla: è semplicemente vero o falso.

Ti consigliamo di utilizzare XRegExp quando devi lavorare con un set specifico di caratteri di Unicode, l’autore di questa libreria ha mappato tutti i tipi di set di caratteri regionali rendendo più semplice il lavoro con lingue diverse.

Ho notato qualcosa di veramente strano con \b quando si utilizza Unicode:

 /\bo/.test("pop"); // false (obviously) /\bä/.test("päp"); // true (what..?) /\Bo/.test("pop"); // true /\Bä/.test("päp"); // false (what..?) 

Sembra che il significato di \b e \B sia invertito, ma solo se usato con Unicode non ASCII? Potrebbe esserci qualcosa di più profondo qui, ma non sono sicuro di cosa sia.

In ogni caso, sembra che la parola limite sia il problema, non i caratteri Unicode stessi. Forse dovresti semplicemente sostituire \b con (^|[\s\\/-_&]) , dato che sembra funzionare correttamente. (Rendi la tua lista di simboli più completa della mia, però).

La mia idea è di cercare con i codici che rappresentano le lettere finlandesi

new RegExp("\\b"+asciiOnly(searchterm), "gi").test(asciiOnly(title))

La mia idea originale era di usare la semplice encodeURI ma il segno% sembrava interferire con la regexp.

http://jsfiddle.net/7TsxB/5/

Ho scritto una funzione grezza usando encodeURI per codificare ogni personaggio con il codice su 128 ma rimuovendo la sua% e aggiungendo ‘QQ’ all’inizio. Non è il miglior indicatore, ma non ho potuto ottenere il funzionamento alfanumerico.

Ho avuto un problema simile, ma ho dovuto sostituire una serie di termini. Tutte le soluzioni, che ho trovato, non hanno funzionato, se due termini erano nel testo uno accanto all’altro (perché i loro limiti si sovrapponevano). Quindi ho dovuto usare un approccio leggermente modificato:

 var text = "Ještě. že; \"už\" à. Fürs, 'anlässlich' že že že."; var terms = ["à","anlässlich","Fürs","už","Ještě", "že"]; var replaced = []; var order = 0; for (i = 0; i < terms.length; i++) { terms[i] = "(^\|[ \n\r\t.,;'\"\+!?-])(" + terms[i] + ")([ \n\r\t.,;'\"\+!?-]+\|$)"; } var re = new RegExp(terms.join("|"), ""); while (true) { var replacedString = ""; text = text.replace(re, function replacer(match){ var beginning = match.match("^[ \n\r\t.,;'\"\+!?-]+"); if (beginning == null) beginning = ""; var ending = match.match("[ \n\r\t.,;'\"\+!?-]+$"); if (ending == null) ending = ""; replacedString = match.replace(beginning,""); replacedString = replacedString.replace(ending,""); replaced.push(replacedString); return beginning+"{{"+order+"}}"+ending; }); if (replacedString == "") break; order += 1; } 

Vedi il codice in un violino: http://jsfiddle.net/antoninslejska/bvbLpdos/1/

L'espressione regolare è ispirata a: http://breakthebit.org/post/3446894238/word-boundaries-in-javascripts-regular

Non posso dire di trovare la soluzione elegante ...

Quello che stai cercando è lo standard dei confini delle parole Unicode:

http://unicode.org/reports/tr29/tr29-9.html#Word_Boundaries

Esiste un’implementazione JavaScript qui (unciodejs.wordbreak.js)

https://github.com/wikimedia/unicodejs