rescue
節があるから複数行だ、というご指摘もあるでしょうが、そこはご容赦を。
#イディオム
マッチしない場合には空文字列を返すことにします。
begin
'%d:%d' % time_str.match(/(\d\d)時(\d\d)分/).captures
rescue
""
end
ムリに一行にすることも出来ますが、読みづらいので使わないほうが良いでしょう。
begin '%d:%d' % time_str.match(/(\d\d)時(\d\d)分/).captures rescue "" end
(コメント反映追記1)後置
rescue
文なら読みやすさに問題なし
'%d:%d' % time_str.match(/(\d\d)時(\d\d)分/).captures rescue ""
>(コメント反映追記2)時分を`Array#join`で繋げてしまう
>```ruby
time_str.match(/(\d{2})時(\d{2})分/).captures.join(":")
(コメント反映追記3)対象文字列の必要部分が数字2文字×2なので、数字2文字を
String#scan
で取得して配列化、それをArray#join
で繋げる
time_str.scan(/\d{2}/).join(':')
#解説
##部分マッチ抜き出し
`String#match`は`MatchData`オブジェクトを返します。
`MatchData`はマッチ全体`$&`及び部分マッチ(`$1`, `$2`, …)を含みます。このため単純に`MatchData#to_a`を使うと
```ruby
"12時34分".match(/(\d\d)時(\d\d)分/).to_a
=> ["12時34分", "12", "34"]
のようにマッチ全体も含んでいます。
ここで使いたいのは部分マッチ情報だけなのでMatchData#captures
を使います。
"12時34分".match(/(\d\d)時(\d\d)分/).captures
=> ["12", "34"]
ただし、部分マッチがなかった場合にMatchData#captures
はnil
を返すので、その対策としてrescue
しています。
##フォーマット
MatchData#captures
で得られた配列をString#%
でフォーマットします。
'%d:%d' % "12時34分".match(/(\d\d)時(\d\d)分/).captures
=> "12:34"
私はString#%
の書き方に慣れていますが、違和感を感じる場合にはKernel.#format
やKernel.#sprintf
なども使えます。ただし、Kernel.#format
やKernel.#sprintf
の第2引数は配列を受けられないのでsplat(*
)で開く必要があります。
format('%d:%d', *("12時34分".match(/(\d\d)時(\d\d)分/).captures))
=> "12:34"
#参考リンク(るりま)