将不间断空格转换为 Ruby 中的空格

Posted

技术标签:

【中文标题】将不间断空格转换为 Ruby 中的空格【英文标题】:Convert non-breaking spaces to spaces in Ruby 【发布时间】:2011-02-05 01:06:52 【问题描述】:

我遇到的情况是,当编码为 utf-8 json 时,有时会使用\u00a0(不间断空格)而不是空格来发送来自 html 文本区域或输入的用户输入数据。

我认为这是 Firefox 中的一个错误,因为我知道用户不是故意放入不间断空格而不是空格。

Ruby 中还有两个 bug,其中一个可以用来对抗另一个。

无论出于何种原因,\s\u00a0 不匹配。

但是[^[:print:]],绝对不应该匹配)和\xC2\xA0 都将匹配,但我认为这些不是处理问题的理想方法。

还有其他解决此问题的建议吗?

【问题讨论】:

哪个 Ruby 版本?在 1.9.2 /\u00a0/ 中匹配。 \s 不匹配 \u00a0 \u00a0 匹配 1.9,但我不确定 1.8 规则#1:当你认为你在一个非常流行的程序中发现了一个错误,尤其是在一些经过测试和广泛使用的程序中,比如 Firefox 的 textarea 处理,非常安静和仔细地检查你的测试. 100 次中有 99 次问题都在你身边。当我看到文本字段中出现不间断空格时,人们可能会在其中粘贴文本,我怀疑是 Microsoft Word 或设置为替换   的编辑器。对于空间。您可以通过创建一个页面、在其中放置一个文本区域并尝试复制问题来轻松测试您的理论。 【参考方案1】:

使用/\u00a0/ 匹配不间断空格。例如s.gsub(/\u00a0/, ' ') 将所有不间断空格转换为常规空格。

使用/[[:space:]]/ 匹配所有空格,包括Unicode 空格,如不间断空格。这与 /\s/ 不同,后者仅匹配 ASCII 空格。

另请参阅:Ruby Regexp documentation

【讨论】:

看unicode.org/versions/Unicode6.2.0/ch06.pdf - 空格字符。但 id 看起来确实不完整 将我的答案修复为简单地使用[[:space]](自我注意:不是[:space])。 "s.gsub(/\u00a0/, ' ') " 是我一直在寻找的。​​span> @JoLiss 您的答案是正确的,但是您的“自我说明”缺少尾随冒号。我自己也多次犯过同样的错误。【参考方案2】:

如果您不能将 \s 用于 Unicode 空白,这是 Ruby 正则表达式实现中的一个错误,因为根据UTS#18 “Unicode Regular Expressions” Annex C on Compatibility Properties \s绝对需要匹配任何 Unicode 空白代码观点。

没有回旋余地,因为详细说明标准建议和 POSIX 兼容性的两列对于 \s 案例是相同的。您无法记录解决此问题的方法:如果您不这样做,您就违反了 Unicode 标准,尤其是 UTS#18 的 RL1.2a。

如果您不符合 RL1.2a,则不符合 1 级要求,这是在 Unicode 上使用正则表达式所需的最基本和最基本的功能。没有它,你几乎迷路了。 这就是标准存在的原因。我记得 Ruby 也未能满足其他几个 1 级要求。因此,如果您确实需要使用正则表达式处理 Unicode,您可能希望使用至少满足 1 级的编程语言。

请注意,您不能使用像 \pZs 这样的 Unicode 通用类别属性来代表 \pWhitespace。这是因为 Whitespace 属性是派生属性,而不是一般类别。其中还包含控制字符,而不仅仅是分隔符。

【讨论】:

【参考方案3】:

回答问题的实际功能 IRB 代码示例,带有最新的 Rubies(2012 年 5 月)

红宝石 1.9

require 'rubygems'
require 'nokogiri'
RUBY_DESCRIPTION # => "ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]"
doc = '<html><body> &nbsp; </body></html>'
page = Nokogiri::HTML(doc)
s = page.inner_text
s.each_codepoint |c| print c, ' '  #=> 32 160 32
s.strip.each_codepoint |c| print c, ' '  #=> 160
s.gsub(/\s+/,'').each_codepoint |c| print c, ' '  #=> 160
s.gsub(/\u00A0/,'').strip.empty? #true

红宝石 1.8

require 'rubygems'
require 'nokogiri'
RUBY_DESCRIPTION # => "ruby 1.8.7 (2012-02-08 patchlevel 358) [x86_64-linux]"
doc = '<html><body> &nbsp; </body></html>'
page = Nokogiri::HTML(doc)
s = page.inner_text # " \302\240 "
s.gsub(/\s+/,'') # "\302\240"
s.gsub(/\302\240/,'').strip.empty? #true

【讨论】:

【参考方案4】:

无论出于何种原因,\s 都与 \u00a0 不匹配。

我认为“不管是什么原因”都是不应该的。只有 POSIX 和 \p 构造字符类是 Unicode 感知的。字符类缩写不是:

Sequence   As[...]        Meaning
     \d    [0-9]          ASCII decimal digit character
     \D    [^0-9]         Any character except a digit
     \h    [0-9a-fA-F]    Hexadecimal digit character
     \H    [^0-9a-fA-F]   Any character except a hex digit
     \s    [ \t\r\n\f]    ASCII whitespace character
     \S    [^ \t\r\n\f]   Any character except whitespace
     \w    [A-Za-z0-9\_]  ASCII word character
     \W    [^A-Za-z0-9\_] Any character except a word character

【讨论】:

哦,它是应该,好吧。它只是没有。看我的回答。 它在规范中和在代码中是有区别的。它是否应该因为规范现在是一个有争议的问题,因为它不存在,无论我们多么希望它在那里,直到核心团队中的某个人决定添加它.所以,现实是,它不应该工作,因为它没有被编码。也许在未来的转速会改变。我希望看到它符合规格,但他们没有问我。 这是一个非常奇怪的事情。 tchrist 是绝对正确的,并且说某些“不应该起作用”因为它目前不起作用是我一段时间以来读到的最好的空洞事实。无论哪种方式 - [[:space:]] 上的 gsub 直到有人让 Ruby 真正符合标准。【参考方案5】:

对于旧版本的 ruby​​ (1.8.x),修复是问题中描述的。

这已在 ruby​​ 1.9+ 的较新版本中得到修复。

【讨论】:

你能说得更具体些吗?我刚刚在 1.9.3p194 上遇到了同样的问题,这是相当 1.9ish。 \s 不匹配 unicode 不间断空格,但 \u00a0 匹配。【参考方案6】:

虽然与 Ruby 无关(也与这个问题没有直接关系),但问题的核心可能Alt+Space on Macs 会产生一个不间断的空间。

这可能会导致各种奇怪的行为(尤其是在终端中)。

对于那些对更多细节感兴趣的人,我前段时间写了关于这个话题的“Why chaining commands with pipes in Mac OS X does not always work”。

【讨论】:

以上是关于将不间断空格转换为 Ruby 中的空格的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ruby,当术语之间可能存在可变空格时,如何将字符串转换为数组?

Apache POI 异常空白(已解决:\u00A0 不间断空格)

为啥 QProcess 将我的参数中的“=”转换为空格

如何修复/转换 Sublime Text 中的空格缩进?

如何在 Netbeans 8.2 中转换选项卡中的空格?

将多个文件中的空格转换为制表符 Sublime Text 2