From: Tanaka Akira Date: 2003-08-05T19:13:48+09:00 Subject: [ruby-dev:21146] Regexp.alt(pat1, pat2, ...) 提案なのですが、複数の Regexp (や String) を | でつなぐ Regexp.alt というメソッドを用意しませんか。 つまり、 rs = [/a/, /b/, /c/] Regexp.alt *rs #=> /(?-mix:a)|(?-mix:b)|(?-mix:c)/ というようなものです。 実装は、次のようなもの(を C で実装したもの)を想定しています。 def Regexp.alt(*args) case args.length when 0 /(?!)/ when 1 if Regexp === args[0] args[0] else arg = args[0] if arg.respond_to? :to_str arg = arg.to_str else raise TypeError, "cannot convert #{arg.class} to String" end Regexp.new(Regexp.quote(arg)) end else code = nil source = args.map {|arg| if Regexp === arg if arg.kcode if code && code != arg.kcode raise ArgumentError, "mixed kcode: #{args.inspect}" end code = arg.kcode end arg.to_s elsif arg.respond_to? :to_str Regexp.quote(arg.to_str) else raise TypeError, "cannot convert #{arg.class} to String" end }.join('|') Regexp.new(source, nil, code) end end 用途はそれなりにあって、標準添付のライブラリをざっと眺めただけでも次の ものが見つかります。 lib/cgi.rb: string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/ni) do lib/cgi.rb: string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/ni) do lib/date/format.rb: PARSE_MONTHPAT = ABBR_MONTHS.keys.join('|') lib/date/format.rb: PARSE_DAYPAT = ABBR_DAYS. keys.join('|') lib/uri/common.rb: }.join('|') + ')' + PATTERN::X_ABS_URI, lib/webrick/httpserver.rb: @scanner = Regexp.new("^(" + k.join("|") +")(?=/|$)") また、私が最近書いたプログラムでも、2ヶ所、関係ないクラスの実装で必要 になり、プログラムのクラスのメソッドとするよりも、Regexp のメソッドと するほうが適切だと思いました。(だからこうして提案しているわけですが。) また、join('|') には次のような微妙な点があり、ただ join('|') するだけ では潜在的に問題が発生する可能性があるため、ユーザに join('|') を書か せるよりもプリミティブとして提供したほうが良いと思います。 * 引数が 0個の場合、| の単位元のφに対応する、まったくマッチしないパター ン (たとえば /(?!)/) にするのが適切なのに、join('|') だと空文字列に マッチするようになってしまう。 * join('|') はパターンを String として扱わなければならず、昨今の傾向に そぐわない。(String 中のメタキャラクタが効いてしまう) * 1.9 への互換性を考えた場合、kcode が混ざっている場合は例外にするのが 適切な気がするけれど、1.8 の join('|') だと検出されない。 なお、 Regexp.alt *rs は rs.join('|') よりもちょっと長いわけですが、Regexp リテラル中の一部で使 われる場合には join('|') は (?:...) で括らないといけないので、 /xxx#{Regexp.alt *rs}xxx/ は /xxx(?:#{rs.join('|')})xxx/ に比べて短くなり、記号が減って読みやすくな る(と思う)こともあわせれば、それなりに使いやすくなっていると思います。 -- [田中 哲][たなか あきら][Tanaka Akira]