Ruby 中如何大写字符串中的首字母

upcase方法大写整个字符串,但我只需要大写第一个字母。

此外,我需要支持几种流行的语言,如德语和俄语。

我该怎么做?

158459 次浏览

使用 capitalize.From 绳子文档:

返回 str 的副本,其中第一个字符转换为大写,其余字符转换为小写。

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"

这取决于使用哪个 Ruby 版本:

Ruby 2.4及更高版本:

它只是工作,因为 Ruby v2.4.0支持 Unicode 大小写映射:

"мария".capitalize #=> Мария

Ruby 2.3及以下版本:

"maria".capitalize #=> "Maria"
"мария".capitalize #=> мария

问题是,它不能做你想让它做的事情,它输出 мария而不是 Мария

如果你正在使用 Rails,有一个简单的解决方案:

"мария".mb_chars.capitalize.to_s # requires ActiveSupport::Multibyte

否则,您将不得不安装 Unicode gem 并像下面这样使用它:

require 'unicode'


Unicode::capitalize("мария") #=> Мария

Ruby 1.8:

一定要使用 编码神奇的评论:

#!/usr/bin/env ruby


puts "мария".capitalize

给出 invalid multibyte char (US-ASCII),同时:

#!/usr/bin/env ruby
#coding: utf-8


puts "мария".capitalize

工作没有错误,但也看到“ Ruby 2.3和更低”部分的实际大小写。

不幸的是,机器不可能正确地大写/小写/大写。它需要太多的上下文信息,计算机无法理解。

这就是为什么 Ruby 的 String类只支持 ASCII 字符的大写,因为这里至少有定义良好的 有点

我说的“上下文信息”是什么意思?

例如,要正确地大写 i,您需要知道文本所使用的语言。例如,英语只有两个 i: 大写的 I不带点,小写的 i不带点。但土耳其语有四个 i: 大写 I没有点,大写 İ有点,小写 ı没有点,小写 i有点。所以,在英语 'i'.upcase # => 'I'和土耳其语 i0。换句话说: 由于 i1可以返回两个不同的结果,这取决于语言,很明显不可能正确地大写一个单词而不知道它的语言。

但是 Ruby 不懂这种语言,它只知道编码。因此,使用 Ruby 的内置功能正确地大写字符串是不可能的。

更糟糕的是: 即使 懂得这种语言,有时也不可能正确地使用大写。例如,在德语中,'Maße'.upcase # => 'MASSE'(梅斯很大的复数,意思是 测量)。但是,'Masse'.upcase # => 'MASSE'(意思是 质量)。那 'MASSE'.capitalize是什么?换句话说: 正确的资本化需要全面的人工智能。

因此,Ruby 不会有时候给出错误的答案,而是有时候选择不给出答案 完全没有,这就是为什么非 ASCII 字符在 downcase/upcase/Capitalize 操作中会被忽略的原因。(当然,这也会导致错误的结果,但至少它很容易检查。)

字符串第一个单词的首字母大写

"kirk douglas".capitalize
#=> "Kirk douglas"

每个单词的首字母大写

铁路:

"kirk douglas".titleize
=> "Kirk Douglas"

或者

"kirk_douglas".titleize
=> "Kirk Douglas"

红宝石:

"kirk douglas".split(/ |\_|\-/).map(&:capitalize).join(" ")
#=> "Kirk Douglas"

或者

require 'active_support/core_ext'
"kirk douglas".titleize

这样我们就知道怎么把第一个字母大写其他字母就不用管了因为有时候这就是我们想要的:

['NASA', 'MHz', 'sputnik'].collect do |word|
letters = word.split('')
letters.first.upcase!
letters.join
end


=> ["NASA", "MHz", "Sputnik"]

调用 capitalize将导致 ["Nasa", "Mhz", "Sputnik"]

你可以使用 mb_chars:

class String


# Only capitalize first letter of a string
def capitalize_first
self[0] = self[0].mb_chars.upcase
self
end


end

示例:

"ümlaute".capitalize_first
#=> "Ümlaute"

Rails 5 +

从 ActiveSupport 和 Rails 5.0.0. beta4开始,您可以使用这两种方法中的一种: String#upcase_firstActiveSupport::Inflector#upcase_first

"my API is great".upcase_first #=> "My API is great"
"мария".upcase_first           #=> "Мария"
"мария".upcase_first           #=> "Мария"
"NASA".upcase_first            #=> "NASA"
"MHz".upcase_first             #=> "MHz"
"sputnik".upcase_first         #=> "Sputnik"

查看“ Rails 5: New upcase _ first Method”获取更多信息。

下面是另一种将字符串中的每个单词大写的方法。\w不能将西里尔字符或拉丁字符与变音符匹配,但 [[:word:]]可以。upcasedowncasecapitalizeswapcase直到2016年发布的 Ruby2.4.0才适用于非 ASCII 字符。

"aAa-BBB ä мария _a a_a".gsub(/\w+/,&:capitalize)
=> "Aaa-Bbb ä мария _a A_a"
"aAa-BBB ä мария _a a_a".gsub(/[[:word:]]+/,&:capitalize)
=> "Aaa-Bbb Ä Мария _a A_a"

[[:word:]]匹配以下类别中的字符:

Ll (Letter, Lowercase)
Lu (Letter, Uppercase)
Lt (Letter, Titlecase)
Lo (Letter, Other)
Lm (Letter, Modifier)
Nd (Number, Decimal Digit)
Pc (Punctuation, Connector)

[[:word:]]匹配“标点符号,连接器”(Pc)类别中的所有10个字符:

005F _ LOW LINE
203F ‿ UNDERTIE
2040 ⁀ CHARACTER TIE
2054 ⁔ INVERTED UNDERTIE
FE33 ︳ PRESENTATION FORM FOR VERTICAL LOW LINE
FE34 ︴ PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
FE4D ﹍ DASHED LOW LINE
FE4E ﹎ CENTRELINE LOW LINE
FE4F ﹏ WAVY LOW LINE
FF3F _ FULLWIDTH LOW LINE

这是另一种仅将字符串的第一个字符转换为大写的方法:

"striNG".sub(/./,&:upcase)
=> "StriNG"

我的版本是:

class String
def upcase_first
return self if empty?
dup.tap {|s| s[0] = s[0].upcase }
end
def upcase_first!
replace upcase_first
end
end


['NASA title', 'MHz', 'sputnik'].map &:upcase_first  #=> ["NASA title", "MHz", "Sputnik"]

还要检查:
Https://www.rubydoc.info/gems/activesupport/5.0.0.1/string%3aupcase_first
Https://www.rubydoc.info/gems/activesupport/5.0.0.1/activesupport/inflector#upcase_first-instance_method