将不间断空格转换为 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> </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> </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,当术语之间可能存在可变空格时,如何将字符串转换为数组?