Javascript RegExp + Word边界+ unicode字符

use*_*520 40 javascript regex unicode

我正在建立搜索,我将使用它的javascript自动完成.我来自芬兰(芬兰语)所以我必须处理一些特殊的角色,如ä,ö和å

当用户在搜索输入字段中键入文本时,我尝试将文本与数据匹配.

如果用户输入例如"ää",则这是一个不能正常工作的简单示例."ä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);   
}
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/7TsxB/

那么我怎样才能让这些ä,ö和å字符与javascript正则表达式一起使用?

我想我应该使用unicode代码但是我应该怎么做?这些字符的代码是:[\ u00C4,\ u00E4,\ u00C5,\ u00E5,\ u00D6,\ u00F6]

=>äÄåÅöÖ

mow*_*ker 38

Regex似乎存在问题,并且字边界\b与字符串的开头匹配,其中起始字符超出正常的256字节范围.

而不是使用\b,尝试使用(?:^|\\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);   
}
Run Code Online (Sandbox Code Playgroud)

分解:

(?:括号()在Regex 中形成一个捕获组.括号以问号开头,冒号?:形成非捕获组.他们只是将条款组合在一起

^ 插入符号匹配字符串的开头

| 条形图是"或"运算符.

\s匹配空格(\\s在字符串中显示,因为我们必须转义反斜杠)

) 关闭小组

因此\b,我们使用与字符串OR空格的开头匹配的非捕获组,而不是使用匹配字边界而不适用于unicode字符的字符串.

  • 这不是一个正确的解决方案.`(?:^ | \\ s)`不是像`\ b`那样的零宽度断言,它将消耗匹配中的字符.一个积极的前瞻是一个更好的主意(`(?= ^ | \\ s)`),但只会在匹配后工作,因为仍然不支持lookbehind.此外,单词边界不仅仅是空格和字符串边界,还有大量其他字符. (12认同)
  • “试试这个”不是解决方案。提供一些关于*为什么*建议的正则表达式有效的信息。`(?:^|\\s)` 到底有什么作用?你根本不解释这个解决方案。 (3认同)

Noa*_*tas 18

\bJavaScript RegEx中的字符类实际上只对简单的ASCII编码有用. \b是字符串\w\W集合之间的边界的快捷代码,以及\w字符串的开头或结尾.这些字符集仅考虑ASCII"单词"字符,其中\w等于[a-zA-Z0-9_]并且\W是该类的否定.

这使得RegEx角色类在处理任何真实语言方面基本无用.

\s 如果搜索条件仅由空格分隔,则应该适用于您想要执行的操作.

  • +1,但是`\ b`不是像`\ w`和`\ s`那样的字符类缩写,它是一个零宽度的断言,如`\ A`,`$`和lookarounds. (9认同)

max*_*tti 13

这个问题很老,但我认为我找到了一个更好的解决方案,用于使用unicode字母的正则表达式中的边界.使用XRegExp,您可以实现有效的\ b边界扩展它

XRegExp('(?=^|$|[^\\p{L}])')
Run Code Online (Sandbox Code Playgroud)

结果是4000多个字符长,但似乎工作很好.

一些解释:(?=)是一个零长度前瞻,它查找开始或结束边界或非字母unicode字符.最重要的想法是前瞻,因为\ b不会捕获任何东西:它只是真或假.


and*_*efs 7

\b 是字母和非字母字符之间转换的快捷方式,反之亦然。

更新和改进max_masseti的答案:

随着/uES2018 中 RegEx 修饰符的引入,您现在可以\p{L}用来表示任何 unicode 字母,并且\P{L}(注意大写P)表示除此之外的任何内容。

编辑:以前的版本不完整。

像这样:

const text = 'A Fé, o Império, e as terras viciosas';

text.split(/(?<=\p{L})(?=\P{L})|(?<=\P{L})(?=\p{L})/);

// ['A', ' Fé', ',', ' o', ' Império', ',', ' e', ' as', ' terras', ' viciosas']
Run Code Online (Sandbox Code Playgroud)

我们使用lookbehind(?<=...)来查找字母,使用lookahead(?=...)来查找非字母,反之亦然。


mic*_*nic 6

当你必须处理来自Unicode的一组特定字符时,我建议你使用XRegExp,这个库的作者映射了所有类型的区域字符集,使得使用不同语言的工作变得更容易.


Hei*_*ang 1

我的想法是用代表芬兰字母的代码进行搜索

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

我最初的想法是使用 plain encodeURI,但 % 符号似乎会干扰正则表达式。

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

我使用encodeURI编写了一个粗略的函数,用超过128的代码对每个字符进行编码,但删除了它的%并在开头添加了“QQ”。它不是最好的标记,但我无法让非字母数字工作。