まつもと ゆきひろです.

In message "[ruby-list:1206] Re: ruby 0.99.3-961204"
    on 96/12/05, sinara / blade.nagaokaut.ac.jp <sinara / blade.nagaokaut.ac.jp> writes:
|
|原です。

|> これはもともとのsuccの定義を変更すべきでしょうね.
|> succって結構面倒なので,rubyで書き直したくないんですよ.せっ
|> かくあるんだから.
|
|あれ?分からないです。「書き直したくないので定義を変更しない」
|のでは? succ はそのままに upto の定義に succ を使うのをやめた
|らいいんじゃないかと思うんですけど。いまさら無理かな。

まずsuccとuptoは表裏一体なので,動きを合わせたい(jcode.rbで
uptoを書き換えるならsuccも書き換えたい)のが,主な理由です.
さらにuptoはperlのstring increment magicに該当する処理を行っ
ているので,もともとの原さんのuptoでは仕様を満足していません.

|> |後、/./ は "\n" にマッチしないので、jtr の引数には出来ません。
|> |これは仕様ということにしますか。
|> 
|> うーん,考えさせてください.

こいつはできるようになりました.新しいjcode.rbを後ろにつけて
おきます.

|そういえば Perl5 で . を \n にマッチさせる /s オプションという
|のが出来たのでそれを導入したらいかがでしょう。ついでに $* = 1
|に相当する /m オプションというのもあるけれど、、、。

まずrubyはいつも複数行に対応しています.つまりいつでもmオプ
ションを指定していることになりますね.sオプションとかは悩ま
しいですねえ.

正規表現ルーチンは借りもので中身を十分に理解していないので,
あまり改造できないんですよね.本当はperl5の拡張正規表現に対
応させたり,速度を改善したいとは思っているのですけど.

ASCIIだけを考えるならそんなに難しくないと思っているのですが,
日本語の取扱を考えるとちょっと私の能力を越えます.できればど
なたかに助けて頂きたいですね.

|それから、"abc" =~ /abc$/ と "abc\n" =~ /abc$/ は両方真です。
|後者が偽になるオプションもあったらいいかも。

perlのmオプションの逆ですね.

|ついでだ。^^; 要望です。

マッチの情報を配列で返せれば満足できますか?
たとえば

 "a;b;c;" =~ /(.);(.);(.);/
 array = $~.to_a

のような形で.gpickはちょっと違うもののようですけど.

|さらに「反復子」のある正規表現
|
|while( "abc" =~ /./g ) { print $&, "\n" }
|
|に相当する
|
|"abc".each_match(/./) { print $&, "\n" }
|
|もあったらいいなあ。

正規表現のgオプションは純粋に実装上の都合でなかなか難しいの
ですが(スロットに空きがない),文字単位のマッチイテレータとい
うのはあっても良いと思います.上のgpick相当もこれがあれば簡
単ですし.

で,これは実現するにはString#grepが行単位でなく文字単位でマッ
チすれば良いようにも思いますけど.どうなんでしょう? もとも
とString#grepを行単位にする必然性はあまりないようですし.

                                まつもと ゆきひろ /:|)

-- jcode.rb
# jcode.rb - ruby code to handle japanese (EUC/SJIS) string

class String
  alias original_succ succ
  private :original_succ

  def succ
    if self[-2] && self[-2] & 0x80 != 0
      s = self.dup
      s[-1] += 1
      return s
    else
      original_succ
    end
  end

  def upto(to)
    return if self > to

    curr = self
    tail = self[-2..-1]
    if tail.length == 2 and tail  =~ /^.$/ then
      if self[0..-2] == to[0..-2]
	for c in self[-1] .. to[-1]
	  yield self[0..-2]+c.chr
	end
      end
    else
      loop do
	yield curr
	return if curr == to
	curr = curr.succ
	return if curr.length > to.length
      end
    end
    return nil
  end

  def _expand_ch
    a = []
    split(/(.-.)|/).each do |r|
      if r =~ /(.)-(.)/
	if $1.length != $2.length
	  next
	elsif $1.length == 1
	  $1[0].upto($2[0]) { |c| a.push c.chr }
	else
	  $1.upto($2) { |c| a.push c }
	end
      elsif r.length > 0
        a.push r
      end
    end
    a
  end

  def tr(from, to)
    afrom = from._expand_ch
    ato = to._expand_ch
    i = 0
    self.split(//).collect{ |c|
      if i = afrom.index(c)
        if i < ato.size then ato[i] else ato[-1] end
      else
        c
      end
    }.join("")
  end

  alias jtr tr        
end