[#47955] るびま記事募集:FiberとかSinatra/PadrinoとかBundlerとか — Makoto Kuwata <kwa@...>

桑田といいます。るびま編集部に入りました。

17 messages 2011/04/11

[#48016] 文字列を正規表現にマッチする部分と他の部分に分割 — "5.5" <5.5@...>

5.5 です。

12 messages 2011/04/28

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

From: "Y. NOBUOKA" <nobuoka@...>
Date: 2011-04-30 10:25:55 UTC
List: ruby-list #48022
5.5 さん

信岡です。

>> result = ''
>> str = 'ab12cd'
>> while true do
>>    i = ( str =~ /\d+/ )
>>    result<<  $`.upcase<<  "<#{$&}>"
>>      str = $'
>> end
>> result<<  str #=>  "AB<12>CD"
>
> これだとループの二回めで =~ が失敗し,$`.upcase で例外が発生しますが,

ああっ、ごめんなさい。 メールを書きながら適当にいじっていて
直すのを忘れてたみたいです。

> 大きなテキストで,かつマッチ箇所が多数あると,大量の文字列ゴミが出ま
> すよね。

そうですね、ごみは出てしまいますね。 ごみを出さないようにするには、
$' を str に代入するのではなく、マッチした位置を index として記録しておいて、
String#match メソッドの第 2 引数に渡すような処理にするとか、すれば
いいのでしょうか。

>> 正規表現中にグルーピングのための括弧があると、とのことですが、
>> グルーピングにはグルーピングのための記法 ("(?:XXX)" の形式) が
>> あるので、これを用いれば問題にはならないと思います。
>
> そうなのですが,以下の理由で避けました。
>
> [1] /(\d).\1/ のように正規表現中で後方参照を使いたい場合もある。
> [2] あまり慣れていない人に使ってもらうツールを考えていたので,
>  エンドユーザーに (?: ) の使用を強いるのが憚られた。
> [3] ブロック内でマッチデータを積極的に使いたい場合もある。

なるほど。
後方参照のための括弧は 「キャプチャリングのための括弧」 であって、
「グルーピングのための括弧」 ではないので、単にグルーピングするだけなら
"(?:XXX)" を使えばいいかなーと思ったのですが、キャプチャリングも必要なら
確かにダメですね。。


実を言うと私も 5.5 さんが提案されたようなメソッドが欲しいなーと思ったことがあって、
その時は自分で適当にそういうメソッドを作ったのですが、確かに実行速度などを
考えると C での実装で提供して貰えるとありがたいですよね。

ただ、String クラスや Regexp クラスに新しく追加すべきメソッドかというとそうでもないなぁ、
とも感じていて。。 追加されるとすれば StringScanner あたりが適当ですかね。

> 一般論として、実際のユースケースを示した方が良いです。
> 特に新しいメソッドを提案するときには。

ちなみに私がそういうメソッドを欲しいと思ったのは、XML のタグ部分 ('<' と '>' で囲まれた部分)
とそれ以外の部分を分けるという処理を書いたときです。 以下のように書けると便利ですよね。

 xml_str.each_segment /<[^>]*>/ do |str, matched|
   if matched
     proc_for_tag( str )
   else
     proc_for_text( str )
   end
 end


-- 
信岡 ゆう (NOBUOKA Yu)

In This Thread