ちなみに

火曜日の空は僕を押しつぶした。

Stringクラスに関するいくつかのTIPS

(この記事はRuby Advent Calendar jp: 2009の9日目の記事です.前の方はrepeatedlyさんで,後の方はno6vさんです.)


今回は原点に立ち帰り、Rubyでもっとも使用するクラスの1つであるStringクラスに関するTIPSをいくつか公開したいと思います。

String#% による文章の整形

特定のフォーマットにしたがって文章を整形する際、Rubyでは Kernel.#sprintf が使用できます。しかし7文字ものメソッド名をタイプするなんて正常なプログラマには耐えられるものではありません。そこで String#% を使うのが一般的となっています。

lang    = 'Ruby'
country = 'jp'
year    = 2009
format = '%s Advent Calendar %s: %d'

# Kernel.#sprintf
puts sprintf(format, lang, country, year)
#=> Ruby Advent Calendar jp: 2009
# String#%
puts format % [lang, country, year]
#=> Ruby Advent Calendar jp: 2009

ただし、コードが読みにくくなるので乱用には気をつけましょう。

文字列整形の三姉妹

Stringクラスの話をしているときに外せないのが center, ljust, rjust の3つメソッドです。それぞれ文字列を、中央、左、右に揃えてくれます。さらに第2引数にパターンを与えてやると、空白部分をそのパターンで埋めてくれます。
百聞は一見にしかず、以下のコードを実行してみて三姉妹の魅力を感じてください。

authors = %w[ ujm yhara mrkn authorNari jugyo ]
max_size = authors.max_by(&:size).size

# 中央揃え
authors.each {|name| puts name.center(max_size) }
# 左揃え
authors.each {|name| puts name.ljust(max_size)  }
# 右揃え
authors.each {|name| puts name.rjust(max_size)  }

姉妹にした理由はとくにありません。

文字列から特定の単語を抜き出す

ある文字列から特定の単語を抜き出すには正規表現が使えます。一般的な方法では Regexp#=~String#match を使うのですが、実は String#[] でも同じことが実現可能です。

str = 'def hoge; p :hoge end'
ptn = /def (.*);/

# 2ステップ必要
p $1 if ptn =~ str
# マッチしないときにエラー
p str.match(ptn)[1]
# シンプル
p str[ptn, 1]

これは僕も明日から使えそうです。(エントリ用に調べたのがバレる)

複数行文字列の行頭の空白を取り除く

みなさんが大好きな Sinatra には、これまたみなさんが大好きな Hamlレンダリングするための haml メソッドが用意されています。しかし、Haml はインデントにうるさいため、一見動きそうな以下のコードでもエラーになってしまいます。

get '/' do
  haml <<-EOS
    %h1 Ruby Advent Calendar jp: 2009
    %p 2009.12.01 - 25
  EOS

こういった場合 String#gsub を使って行頭の空白を取り除くことによってエラーを回避しつつ美しいインデントを保てます。

  haml <<-EOS.gsub(/^ {4}/, '')
    ...
  EOS

単純な正規表現ですが、慣れていないと戸惑う点が2つあります。
1つ目は'^'です。ご存知のとおり行頭にマッチするアンカです。では'\A'とは何が違うのでしょうか?よくブログなんかで自分のコードを載せてみたら、コメントで「Rubyでは先頭にマッチさせるときは '^' ではなく '\A' を使いましょう。」と言われた人も少なくないんじゃないでしょうか?なのになんで今さら'^'を使うんだとお怒りの方もいらっしゃると思います。整理しましょう、先頭にマッチさせる場合は'\A'行頭にマッチさせる場合は '^' を使うのです。つまり今回は各行の行頭にマッチさせたいので '^' を使ったわけです。
もう一点は '{4}' です。正規表現では通常 "できるだけ多く" にマッチするようになっています。しかし、今回の場合はインデントを下げるのが目的です。つまり特定の数だけマッチさせて削除したいのです。そういったときには、量指定子である '{}' を使ってマッチする量を指定することができます。この場合空白4つ分にマッチさせたいので ' {4}' としています。


みなさんは横着せずにちゃんとview用の別ファイルを作りましょうね。

最後に

最後にもっとも便利なメソッドを紹介します。一般的なソフトウェアを開発していると頻繁に「文字列を1文字インクリメントしたい。」という場面に遭遇します。そういったときにためにRubyのStringクラスには便利な succ メソッドが定義されています。以下の様にすることによって、スマートに文字をインクリメントすることが出来て大変便利です。

'a'.succ #=> 'b'
'67'.succ #=> '68'

(::) < Venry method makes you happy!

参考文献

Rubyを深く理解するには、リファレンスマニュアルの熟読は欠かせません。
Ruby リファレンスマニュアル刷新計画(通称、るりま)は、日本語による完全なリファレンスマニュアルの完成を目標に、Rubyコミュニティ(もちろん僕も含む)に多大なる貢献をしているプロジェクトです。まずはるりまの成果物である、リファレンスマニュアルを通読しましょう。そして次はあなたがドキュメントを書く番です。
るりまの閲覧には、okkezさんが公開してくださっているバージョンがおすすめです。http://doc.okkez.net/

(明日は @no6v さんです。どんな内容になるのか楽しみですね。わくわく。)