Rubyでは、他のすべてのものと同じように、Stringはオブジェクトです。
文字列は任意のバイト列(通常は文字)でできていて、他のオブジェクトと同じように初期化したり操作したりできます。
実際、Rubyの最も便利なところのひとつは、文字列(や他のオブジェクト)に対して呼び出せるメソッドがたくさんあり、コードを書く時間を大幅に節約できることです。
この演習では、そうしたメソッドのいくつかを実際に触りながら見ていきましょう。
String.new(...)を使って文字列を作ることもできますが、はるかに一般的なのはリテラルを使う方法です。
使えるリテラルにはたくさんの種類があり、それらは2つのカテゴリーに分かれます。式展開できるものと、できないものです。
もっともよく使うリテラルは、シングルクォートとダブルクォート('...'と"...")です。
シングルクォートでは式展開ができませんが、ダブルクォートではできます。
式展開とは、#{}という記法を使って、ある文字列を別の文字列の中に埋め込むことです。
# Use single quotes when not interpolated
location = 'World'
# And double quotes when interpolated
puts "Hello, #{location}!" #=> "Hello, World!"
また、式展開したい文字列には%{... }、そうでない文字列には%q{...}といった、他のリテラルも使えます。
これは、文字列の中に'や"といった文字が含まれる場合に便利です。
補足:文字列に式展開が含まれていないからといって、必ず式展開できない文字列を使わなければならない、という絶対的なルールはありません。
Rubyの文字列は、配列と同じように考えるとわかりやすいです。
文字列には長さがあり、それぞれの文字はインデックスで参照できます(最初のインデックスは0です)。
my_string = "Some string"
my_string.size #=> 11
my_string[0] #=> 'S'
my_string[1] #=> 'o'
my_string[-1] #=> 'g'
# Find the first index of a character
my_string.index('m') #=> 2
文字列の一部は、インデックスやsliceを使って取り出せます。
my_string = "Some string"
# Find three characters starting with the second character (index 1)
my_string[1, 3] #=> "ome"
my_string.slice(1, 3) #=> "ome"
文字列の値そのものを操作することもできます。 すべてのメソッドについて知るにはRubyのドキュメントを見てみる価値がありますが、よく使う例をいくつか挙げます。
"hello".capitalize #=> "Hello"
"HELLO".downcase #=> "hello"
"hello".center(9) #=> " hello "
" hello ".strip #=> "hello"
"hello world".split(" ") #=> ["hello", "world"]
gsubのようなメソッドを使えば、文字を置き換えることもできます。
# Replace one character with another
"noob".gsub("o","0") #=> "n00b"
# (Advanced) Replace a regular expression
"Ruby really rocks".gsub(/[aieou]/,'') #=> "Rby rlly rcks"
ここまでの例では、いずれも新しいStringが返されます。
ただし、多くのメソッドには!で終わる同等のものがあり、そちらは文字列そのものを変更します。
# Use normal methods to return new strings
my_string = "hello"
my_string.capitalize #=> "Hello"
puts my_string #=> "hello"
# And bang-methods (...!) to modify the object
my_string = "hello"
my_string.capitalize! #=> "Hello"
puts my_string #=> "Hello"
この演習では、ログ行を処理します。
各ログ行は、"[<LEVEL>]: <MESSAGE>"という形式の文字列です。
ログレベルは次の3つです。
INFOWARNINGERRORタスクは3つあり、それぞれがログ行を受け取って、それを使って何かをするよう求めます。 これらのタスクを解く方法はたくさんあります。上の例からお気に入りのメソッドを選んで、どんなコードを書けるか試してみましょう。
LogLineParser#messageメソッドを実装して、ログ行のメッセージを返すようにしてください。
LogLineParser.new('[ERROR]: Invalid operation').message
# => "Invalid operation"
先頭と末尾の空白は取り除いてください。
LogLineParser.new("[WARNING]: Disk almost full\r\n").message
# => "Disk almost full"
LogLineParser#log_levelメソッドを実装して、ログ行のログレベルを返すようにしてください。ログレベルは小文字で返します。
LogLineParser.new('[ERROR]: Invalid operation').log_level
# => "error"
ログ行を整形し直すLogLineParser#reformatメソッドを実装してください。メッセージを先に、そのあとに括弧(())で囲んだログレベルを置きます。
LogLineParser.new('[INFO]: Operation completed').reformat
# => "Operation completed (info)"