2011年4月28日

[ruby-list:48016] 文字列を正規表現にマッチする部分と他の部分に分割

5.5 です。

文字列 S の中で,正規表現 R にマッチする部分とそれ以外の
部分をそれぞれ取得したいときに,どうもうまい方法が見つか
りません。

以下のような String#each_segment メソッドがあると嬉しい
です。(この例は非実用的です)


result=""
"ab12cd".each_segment /\d+/ do |str, match|
result << (match ? "<#{str}>" : str.upcase)
end

result # => "AB<12>CD"

ここで,二つめのブロックパラメーター match は MatchData
オブジェクトです。
str が非マッチ文字列のときは match は nil とします。

マッチ部分とそれ以外の部分を取り出すには,String#split
に括弧付きの正規表現を与える方法もありますが,

"ab12cd".split(/(\d+)/) # => ["ab", "12", "cd"]

正規表現中にグルーピングのための括弧があるとダメですし,
マッチ部分かそうでない部分かをもう一度判定しなければなり
ません。


そこで,strscan を使う方法を考えました。

s=StringScanner.new("ab12cd")

result=""
while offset=s.exist?(/\d+/)
len=offset-s.matched.size
result << s.peek(len).upcase unless len.zero?
result << "<#{s.matched}>"
s.pos=s.pos+offset
end
result << s.rest.upcase unless s.rest.empty?

これ以上簡潔な書き方が思いつきませんでした。
マッチ文字列の間を取り出す手段が無いからです。

いかにも回りくどいですし,非マッチ文字列に対する処理が
二箇所に書かれていて DRY ではありません。

また,pre_match,post_match を使うケースで,元テキストが
非常に大きく,マッチ箇所が多数ある場合には,大量の文字列
ゴミが生じると思います。


汎用性のあるもっとうまい書き方があるのか,それとも提案し
たようなメソッドの導入に意義があるのか,どんなものでしょ
うか。

--
5.5@xxxxx


投稿者 xml-rpc : 2011年4月28日 22:58
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/103233
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。