【问题标题】:Is there a way to use regexp match for characters with tilde?有没有办法对带有波浪号的字符使用正则表达式匹配?
【发布时间】:2010-12-04 23:52:11
【问题描述】:

看看这个:

"nAo".match(/(nao)/i) # => #<MatchData "nAo" 1:"nAo">

"nÃo".match(/(não)/i) # => nil

有办法解决吗?

编辑: 在与 i 标志(忽略大小写)进行正则表达式比较时,ruby 似乎缺乏对 unicode 字符的支持...... 使用 MRI 1.8.7p249

【问题讨论】:

  • 检查您在问题中的假设并相应地更新它。从上面可以看出,Ruby 并没有将 Ã 和 ã 识别为大小写相关,仅此而已。其中,虽然仍然是一个问题,但却是一个不同的问题。
  • Perl 当然可以对 Unicode 应用不区分大小写。默认情况下,它不执行 NFD 样式的规范等价,而是 chr(0x17F) =~ /s/i,例如,其中 017F 是 LATIN SMALL LETTER LONG S。类似地,"N\N{U+C3}O" =~ /n\N{U+E3}o/i。要处理带有组合标记的替代表示,您需要先将模式和字符串都转换为 NFD(规范分解)。
  • 我不熟悉 unicode 问题,但最好提一下您使用的 Ruby 版本。
  • @tchrist,你的意思是“Perl”还是“Ruby”?毕竟这是一个 Ruby 问题。

标签: ruby regex unicode case-insensitive


【解决方案1】:

不了解 Ruby,但大多数正则表达式引擎不理解非 ASCII 字符的大写/小写。您能做的最好的事情是:

/(n[ãÃ]o)/

理解大写/小写关系的问题在于它依赖于语言。 Unicode 只编码字符的形式,而不是含义。因此,unicode 中的大写字符可以有不同的小写字符,具体取决于语言。

SS 为例。在英语中,小写字母为ss,但在德语中可以为ß。另一个例子是字母I,它在英语中是小写i,但在土耳其语中它的小写是ı(没有点)。那是因为土耳其语中的i 是大写的İ(带点)。

因此,大多数正则表达式实现只是放弃并拒绝理解标准 ASCII 以外字符的大写/小写关系。

【讨论】:

  • 问题超出了大写和小写的范围。 Unicode 字符可以通过几种不同的方式定义,并且仍然返回相同的字符视觉表示。见Ready-made versus composite characters。基本上,我们不再在堪萨斯了。 :-)
  • 我当然不会声称大多数正则表达式引擎不能处理 Unicode 大小写! Perl 总是这样,如果你使用(?iu),Java 也会这样做。在 Perl 中,"\N{U+DF}" =~ /ss/i 返回 1。类似地,` "\x{FB03}" =~ /ffi/i` 也是如此。
  • 我实际上发现将模式和字符串转换为 NFD 过于复杂,因此决定坚持使用 slebetman 提出的这个简单的解决方法,稍作调整:string.upcase.match(/NÃO|NAO/) - 它似乎像一个魅力!
【解决方案2】:

尝试为 Ruby 找到一些 unicode normalization 模块。

【讨论】:

    【解决方案3】:

    请注意,Ruby 从 1.9 开始就有更好的字符支持(看起来你运行的是 Ruby 1.8.7)。旧的正则表达式引擎在 Ruby 1.9 中被 Oniguruma 取代。

    http://www.geocities.jp/kosako3/oniguruma/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-22
      • 1970-01-01
      • 2022-01-13
      • 2020-09-03
      相关资源
      最近更新 更多