29

I want to be able to check if a word is already all uppercase. And it might also include numbers.

Example:

GO234 => yes
Go234 => no
Viktor
  • 2,623
  • 3
  • 19
  • 28
Jacob
  • 6,317
  • 10
  • 40
  • 58
  • 3
    I don't know ruby, but I'm sure there is something like `ToUpper`. The check the actual string against this function. – Matthias Dec 16 '11 at 04:01

4 Answers4

55

You can compare the string with the same string but in uppercase:

'go234' == 'go234'.upcase  #=> false
'GO234' == 'GO234'.upcase  #=> true
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
JCorcuera
  • 6,794
  • 2
  • 35
  • 29
  • 2
    This only works for ASCII. From the [fine manual](http://ruby-doc.org/core-1.9.3/String.html#method-i-upcase): "The operation is locale insensitive—only characters “a” to “z” are affected. Note: case replacement is effective only in ASCII region.". – mu is too short Dec 16 '11 at 04:14
  • For not ASCII try .mb_chars, for example: 'ТАК' == 'так'.mb_chars.upcase.to_s – nub Mar 18 '13 at 17:22
  • short and smart solution – Ravindra Jun 24 '15 at 10:43
28
a = "Go234"
a.match(/\p{Lower}/) # => #<MatchData "o">

b = "GO234"
b.match(/\p{Lower}/) # => nil

c = "123"
c.match(/\p{Lower}/) # => nil

d = "µ"
d.match(/\p{Lower}/) # => #<MatchData "µ">

So when the match result is nil, it is in uppercase already, else something is in lowercase.

Thank you @mu is too short mentioned that we should use /\p{Lower}/ instead to match non-English lower case letters.

PeterWong
  • 15,951
  • 9
  • 59
  • 68
  • Although I suspect this will quickly break on non-English alphabets... do ruby REs have any more Unicode-specific support? –  Dec 16 '11 at 04:02
  • I don't think there would be problem as it just matches lower case a to z. I had a quick test in my irb (ruby 1.9.2 p270) and it works fine :) – PeterWong Dec 16 '11 at 04:05
  • 6
    You'd probably want `/\p{Lower}/` with 1.9. Compare `'µ'.match(/[a-z]/)` and `'µ'.match(/\p{Lower}/)` for example. – mu is too short Dec 16 '11 at 04:07
  • 1
    That ([a-z]) assumes that only the a-z characters can be lowercase (e.g. English Alphabet), but not something like щ (lower-case for Russian Щ). –  Dec 16 '11 at 04:08
  • 3
    Best to use the [Unicode properties](http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt) for this sort of thing. – mu is too short Dec 16 '11 at 04:11
  • Then I found that `"щ".upcase == "щ"` instead of `"щ".upcase == "Щ"`. Is there any reason? – PeterWong Dec 16 '11 at 04:14
  • 1
    +1 for learning your lesson and getting it right for posterity. The `upcase` method only works for ASCII: http://ruby-doc.org/core-1.9.3/String.html#method-i-upcase – mu is too short Dec 16 '11 at 04:19
4

I am using the solution by @PeterWong and it works great as long as the string you're checking against doesn't contain any special characters (as pointed out in the comments).

However if you want to use it for strings like "Überall", just add this slight modification:

utf_pattern = Regexp.new("\\p{Lower}".force_encoding("UTF-8"))

a = "Go234"
a.match(utf_pattern) # => #<MatchData "o">

b = "GO234"
b.match(utf_pattern) # => nil

b = "ÜÖ234"
b.match(utf_pattern) # => nil

b = "Über234"
b.match(utf_pattern) # => #<MatchData "b">

Have fun!

Ole Spaarmann
  • 15,845
  • 27
  • 98
  • 160
2

You could either compare the string and string.upcase for equality (as shown by JCorc..)

irb(main):007:0> str = "Go234"
=> "Go234"
irb(main):008:0> str == str.upcase
=> false

OR

you could call arg.upcase! and check for nil. (But this will modify the original argument, so you may have to create a copy)

irb(main):001:0> "GO234".upcase!
=> nil
irb(main):002:0> "Go234".upcase!
=> "GO234"

Update: If you want this to work for unicode.. (multi-byte), then string#upcase won't work, you'd need the unicode-util gem mentioned in this SO question

Community
  • 1
  • 1
Gishu
  • 134,492
  • 47
  • 225
  • 308
  • Wrong, the `upcase` method only works for ASCII so it will miss lower case letters such as µ (Greek) and щ (Cyrillic). – mu is too short Dec 16 '11 at 04:17
  • @muistooshort - updated. The poster gave no indication that he wanted this to work for unicode. So assumed the simplest case... anyways updated! – Gishu Dec 16 '11 at 06:29