【问题标题】:RegExp Range out of order in character class for Unicode CharactersUnicode 字符的字符类中的 RegExp 范围乱序
【发布时间】:2021-11-22 19:10:20
【问题描述】:

我有这个正则表达式:

RegExp(r'[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}\u{200d}]');

当我在https://regex101.com 上使用这个正则表达式时,它正在工作。但是当我在 Dart 中使用这个 RegExp 时,我得到了一个 Range out of order in character class 错误(请注意,当我在 JavaScript 中使用 RegExp 等效项时也会发生同样的情况)。

我很确定这是一个字符串转义错误,但我找不到问题。

我已经在 Dart (r'...') 中尝试了一个原始字符串,转义了 \u{1f300} 中的 \\\u{1f300},但是,两者都不起作用。

【问题讨论】:

  • 你是否传递了u 标志(在 Dart 中为unicode: true)?

标签: javascript regex dart unicode


【解决方案1】:

Unicode 匹配

正如 cmets 中所指出的,匹配 unicode 字符需要正则表达式中的 unicode flag

如果您尝试使用 RegExp('\u123') 简单地匹配一个 unicode 字符,这将失败,原因有两个。

  1. 您不能在正则表达式中包含 unicode 字符。相反,您需要转义它们(例如,使用原始字符串):RegExp(r'\u123')
  2. 这仍然不起作用,因为现在正则表达式尝试评估字符串中的每个字符(如\u 等)。这就是unicode flag 发挥作用的地方:RegExp('\u123', unicode: true)

请注意,对于 3 字节的 unicode 字符,您需要添加花括号,例如RegExp(r'u\{1f300}'。请参阅this question 了解更多信息。


这意味着您的最终正则表达式应如下所示:

RegExp(
  r'[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}'
  r'\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}'
  r'-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}'
  r'\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}'
  r'-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}'
  r'\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}'
  r'-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}'
  r'\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}'
  r'-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}\u{200d}]+',
  unicode: true,
);

字素簇

您可能遇到的另一个问题是,您将无法将跨越多个字符的表情符号与初始正则表达式匹配。请注意,在上面的 sn-p 中,我在末尾添加了一个 + 以匹配跨越多个字符的表情符号。

现在为了匹配单个表情符号,您需要对字符串中的每个单个 字符 运行正则表达式,由 grapheme clusters 定义。这可以使用package:characters 来实现。

一个示例实现可以是found here

【讨论】:

  • 你确定你不能有 Unicode 文字 RegExp 模式吗? RegExp('^[\u{1f300}-\u{1f5ff}]+', unicode: true) 似乎与我匹配有或没有 r 前缀。 (实际上,我更惊讶于它原始字符串一起工作。)
  • @jamesdlin 这很有趣!我的真正意思是你不能使用 unicode 文字 没有 \u 标志 (unicode: true)。我认为无论如何您通常都希望将原始字符串用于正则表达式,因此我会将原始字符串保留在示例中。
  • 它适用于原始字符串,因为\u{1f300} 是支持 Unicode 的正则表达式中代码点的有效正则表达式转义语法。它在解释字符串中有效,因为\u{1f300} 是代理对 "\ud83c\udf00" 的 Dart 字符串转义语法,并且 RegExp 源中的代理对也被解释为启用 Unicode 的 RegExps 中的单个代码点。 unicode 标志是关键,没有那个 \u{1f300} 不是正则表达式转义,[\u{1f300}-\u{1f5ff}] 试图将范围从 }u - 这是无效的,因为 }u 之后在 ASCII 中。这导致了最初的错误。
猜你喜欢
  • 2015-05-15
  • 2011-03-28
  • 2013-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 1970-01-01
相关资源
最近更新 更多