如何在Ruby中大写字符串中的第一个字母


134

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

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

我该怎么做?


4
请注意,某些语言对首字母大写的含义有所不同。在爱尔兰语中,您会执行“ i mBaileÁthaCliath”(“都柏林”中的内容)-小写字母“ m”,大写字母“ B”。(见en.wikipedia.org/wiki/Consonant_mutation#Celtic_languages如果你很好奇,为什么爱尔兰人会做到这一点,为什么它是有道理的。)
詹姆斯·穆尔

3
另外请注意,#capitalize会将所有不是首字母的字母都小写...这并不总是您想要的。 ['space', 'UFO', 'NASA'].collect{|w| w.capitalize} #=> ['Space', 'Ufo', 'Nasa']
Huliax

Answers:


260

这取决于您使用的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及更低版本”部分以获取大写字母。


19
注意,显然"my API is great".capitalize会产生My api is great可能是不希望的行为。所以这个答案并没有真正回答这个问题,因为他只希望将FIRST字母变成大写而其他字母保持不变。
Daniel AR Werner

55

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

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

每个单词的首字母大写

在导轨中:

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

要么

"kirk_douglas".titleize
=> "Kirk Douglas"    

在红宝石中:

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

在rails之外,但仍想使用titleize方法

require 'active_support/core_ext'
"kirk douglas".titleize #or capitalize

1
支持纯Ruby解决方案。太懒了,无法正确启动Rails,这确实
起到

19

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

这就是Ruby的String类仅支持ASCII字符大写的原因,因为那里至少有一些明确的定义。

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

例如,要i正确地大写,您需要知道文本使用的语言。例如,英语只有两个is:I不带点的大写字母和带点的小字母i。但是土耳其语有四个is:大写字母I不带点,大写İ字母带点,小ı不带点,小i带点。因此,用英语'i'.upcase # => 'I'和土耳其语'i'.upcase # => 'İ'。换句话说:由于'i'.upcase可以返回两种不同的结果(取决于语言),因此在不知道其语言的情况下正确地将其大写显然是不可能的。

但是Ruby不懂语言,只懂编码。因此,使用Ruby的内置功能无法正确地将字符串大写。

更糟糕:即使知道的语言,有时不能正确地做资本。例如,在德语中,'Maße'.upcase # => 'MASSE'MaßeMaß的倍数,表示测量值)。但是,'Masse'.upcase # => 'MASSE'(表示质量)。那么,什么是'MASSE'.capitalize?换句话说:正确使用大写字母需要成熟的人工智能。

所以,与其有时还会提供错误的答案,红宝石选择有时给没有答案可言,这就是为什么非ASCII字符简单地获得downcase / upcase /资本运作忽略。(当然,这也会读取错误的结果,但至少很容易检查。)


4
抱歉,但您的论点不能成立。Ruby选择根本不给出答案是不正确的,Ruby总是给出答案,这通常是错误的-例如“мария”。upcase绝不应该返回“мария”,在任何情况下都不正确。而且您对AI需求的看法根本无关紧要-没有什么可以阻止大写重述数组,对于[i] .upcase说['I','İ'],让调用者决定哪个大写字母是相关的在给定的情况下。当前,Ruby对大写和小写之间的转换的处理已失效,仅此而已。
michau 2012年

2
-1因为有一个大写的Eszett。使用某些未完全形式化的区域不能作为该解决方案的证明,仅AI才有可能。
迈克

15

好吧,如此我们知道如何仅将首字母大写,而将其余首字母留空,因为有时需要这样做:

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

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

呼叫capitalize将导致["Nasa", "Mhz", "Sputnik"]


谢谢我一直在寻找的东西,对将标题转换为“句子大小写”非常有用
Good Lux

2
word[0] = word[0].upcase
大卫,

@大卫。没有!这将更改调用#collect的数组中单词的值。那是不好的副作用。
休里亚克斯

我展示了一种简单的方法来大写单词的第一个字母,替换了此解决方案的前三行,我通过使用word变量明确了这一点。当然,如果您有更多的单词,只需在所有单词上调用它们即可!;)words.map{|word| word[0] = word[0].upcase}
David

@大卫。您的代码总计为,#capitalize!而不是#capitalize。后者返回一个新的String,而前者则修改该方法的接收者(在这种情况下,接收者为word,方法为#[])。如果在#collect块中使用了代码,则最终将得到两个不同的数组,每个数组中的String对象相同(并且Strings将被修改)。那不是您通常想要做的。即使您知道这一点,其他读者也应该理解这一点。
休里亚克斯

8

滑轨5+

从Active Support和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:新的upcase_first方法 ”以获取更多信息。


3

使用capitalize。从字符串文档中:

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

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

如果要更改原始字符串,请仅使用感叹号。
Magnar

卫生署谢谢,固定我的错误。
jhwist

5
-1。OP 明确提到德语和俄语文本,这表示非ASCII字符。String#upcase(以及String#downcase)仅针对ASCII字符定义。
约尔格W¯¯米塔格

1
今天使用Ruby 2.5.0,String#upcase似乎可以在非ASCII字符上正常工作。2.5.0 :001 > "мария".upcase => "МАРИЯ"
Huliax

1
@Huliax如已接受的答案中所述,仅从Ruby 2.4.0(2016年发布)以来就是这种情况。
nisetama '19

2

您可以使用mb_chars。这尊重umlaute:

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"

0

下面是将字符串中每个单词大写的另一种方法。\w西里尔字母或拉丁字母与变音符号不匹配,但是匹配[[:word:]]upcasedowncasecapitalize,和swapcase并不适用于非ASCII字符,直到红宝石2.4.0这是在2016年发布。

"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"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.