用正则表达式拆分和替换javascript中的unicode单词

Joh*_*ohn 5 javascript regex unicode split

需要在{}中的unicode字符串中放置unicode单词列表.有我的代码:

var txt = "¿One;one oneé two two two two two twö twöu three;;twä;föur?";
var re = new RegExp("(^|\\W)(one|tw|two two|two|twöu|three|föur)(?=\\W|$)", "gi");
alert(txt.replace(re, '$1 {$2}'));
Run Code Online (Sandbox Code Playgroud)

它返回:

¿{One}; {one} {one}é{two two} {two two} {two} {tw}ö{tw}öu{three} ;; {tw}ä; {föur}?

但应该是:

¿{One}; {one}oneé{two two} {two two} {two}twö{twöu} {three} ;;twä; {föur}?

我做错了什么?

tch*_*ist 14

问题

我究竟做错了什么?

不幸的是,答案是你没有做错任何事.Javascript是.

问题是Javascript不支持Unicode正则表达式,因此在Unicode标准中有详细说明.

然而,有一个相当不错的库叫做XRegExp,它有一个JavaScript插件,可以提供很多帮助.我推荐它,尽管有一些值得注意的警告.你需要知道什么可以做,什么也不能.


它能做什么

  • 纠正了Javascript实现中不一致的各种错误,包括split功能.
  • 从2012年1月开始支持Unicode字符数据库6.1版本所涵盖的BMP代码点.
  • 正确忽略大小写,空格,连字符,优缺点,并强调以Unicode属性名称,每个标准 -一些东西,连渣得到错误的.
  • 支持Unicode通用类别,如\p{L}字母和\p{Sc}货币符号.
  • 支持标准的完整属性名称,如\p{Letter}for \p{L}\p{Currency_Symbol}for \p{Sc}.
  • 支持Unicode脚本属性,如\p{Latin},\p{Greek}\p{Common}.
  • 支持Unicode块属性,例如\p{InBasic_Latin}\p{InMathematical_Alphanumeric_Symbols}.
  • 支持所需要的第1级遵守其他9 Unicode属性:\p{Alphabetic},\p{Uppercase},\p{Lowercase},\p{White_Space},\p{Noncharacter_Code_Point},\p{Default_Ignorable_Code_Point},\p{Any},\p{ASCII},和\p{Assigned}.
  • 支持命名捕获而不是仅编号的捕获,使用标准符号来执行此操作:(?<NAME>?)声明命名组,\k<NAME>按名称对其进行反向,并${NAME}在替换模式中使用(通常result.NAME在代码中使用它).这与Perl 5.10,Java 7,.ɴᴇᴛ和其他几种语言使用的语法相同.通过让你为部件命名而不是仅对它们进行编号,它使复杂的正则表达式更容易编写,这样当你移动东西时就不必重新计算编号的变量了.
  • 支持/sᴀᴋᴀ (?s)模式,使点匹配任何单个代码点,而不是除了换行序列之外的任何内容.大多数其他正则表达式引擎支持此模式.
  • 支持/xᴀᴋᴀ (?x)模式,以便忽略空格和注释(如果未转义).大多数正则表达式引擎都支持此模式.它对于创造清晰易读 - 因此可维护 - 的模式是绝对必不可少的.
  • 即使在不/x使用标准(?#?)符号的模式下也支持嵌入式注释(例如在Perl中看到).这使得您可以将注释放在单独的正则表达式中,而无需一直进入/x模式,这对于开发更复杂的模式通常很重要,允许您逐个构建它们.
  • 支持可扩展性,以便您可以根据需要添加新的令牌类型,例如\a表示ALERT字符或POSIXish字符类.

什么不是

但是,对于它没有做的事情,你应该小心:

  • 不支持完整的Unicode,但只支持平面0的代码点.这是一个禁止的限制,因为Unicode标准要求正则表达式中的星体和非星体代码点之间没有区别.即使Java在JDK7之前也没有这样做.(但是,v2.1.0开发版本确实支持完整的Unicode.)
  • 不支持\X字形集群或\R换行序列.
  • 不支持两部分组成的属性,如\p{GC=Letter},\p{Block=Phonetic_Extensions},\p{Script=Greek},\p{Bidi_Class=Right_to_Left},\p{Word_Break=A_Letter},和\p{Numeric_Value=10}.
  • 它不会根据UTS#18的要求更新操作的字符类快捷方式.标准JavaScript只允许\s匹配Unicode \p{White_Space}属性; 它不允许\d匹配\p{Nd}(虽然有些旧的浏览器能做到这一点呢!),也不\w匹配[\p{Alphabetic}\pM\p{Nd}\p{Pc}],更不用说提供支持Unicode的版本\b\B,所有这些都是支持Unicode的正则表达式的要求的一部分.
  • 它不支持一些常用属性.在实践中,缺少一个\p{digit},或许也是相当有用的\p{Dash},\p{Math},\p{Diacritic},和 \p{Quotation_Mark}属性.
  • 不支持字形集群,例如使用\X甚至通过(?:\p{Grapheme_Base}\p{Grapheme_Extend}*).这是一个非常重要的事情.

解决方法

以下是处理库不遵循Unicode标准的一些地方的一些解决方法:

  • 对于缺失\w,您可以使用[\p{L}\p{Nl}\p{Nd}\p{M}\p{InEnclosedAlphanumerics}].它仅在附带的数字中夸大了事项,因为它们不是\p{Nd}类型数字,它们是唯一被认为是字母数字的数字.
  • \W因此,对于缺失,您可以使用前一个的set-complement,所以[^\p{L}\p{Nl}\p{Nd}\p{M}\p{InEnclosedAlphanumerics}].它仅在附上的数字中夸大了事项.
  • 由于\b实际上是相同的(?:(?<=\w)(?!\w)|(?<!\w)(?=\w)),你可以将该\w定义插入该序列以创建一个支持Unicode的版本\b- 只要JavaScript支持所有四个方向的外观,当我最后检查时,它没有.为了做到这一点,你必须同时具有积极和消极的外观,而不仅仅是前瞻.Javascript忽略了支持这些,至少就我所见.
  • 由于\B实际上是相同的(?:(?<=\w)(?=\w)|(?<!\w)(?!\w)),你可以做同样的事情,但受相同的条件限制.
  • 对于缺失\X,你可以通过使用得到sorta \P{M}\p{M}*,但是错误地拆分了CRLF结构并允许标记相同,所有这些都非常错误.
  • 对于缺失\R,您可以构建一个使用的解决方法(?:\r\n|[\n-\r\u0085\u2028\u2029]).

摘要

结论是JavaScript的正则表达式完全不适合Unicode工作.但是,XRegExp插件更接近于实现可行性.如果你能忍受它的限制,那么这可能比切换到另一种支持Unicode的编程语言更容易.它肯定比无法使用Unicode正则表达式更好.

但是,如果符合标准中规定的Unicode正则表达式的最基本要求(1级支持),它仍然是一个很长的路要走.总有一天你会想要能够匹配字符,无论它们是否有重音符号,或者在数学字母数字符号块中设置,或者使用Unicode案例映射和大小写折叠定义,或者跟随Unicode标准用于字母数字排序或用于行和断字,即使使用插件也无法在Javascript中执行任何操作.

因此,如果您确实需要处理Unicode ,可能需要考虑使用符合Unicode标准的语言.Javascript只是不管理.


ken*_*ytm 5

首先,除非正则表达式是动态的,否则请使用/.../gi表示法.

它返回错误值的问题是因为\W在Javascript中它真的是公正的[^0-9a-zA-Z_].重音字符é不被视为单词字符.您需要手动排除它们.

var re = /(^|[^a-zäéö])(one|tw|two two|two|twöu|three|föur)(?=[^a-zäéö]|$)/gi;
Run Code Online (Sandbox Code Playgroud)