青木です。

  In mail "[ruby-dev:22159] Re: URI.regexp"
    akira yamada / やまだあきら <akira / ruby-lang.org> wrote:

> > 「URIっぽい文字列にマッチする正規表現」を返す機能が URI に
> > 欲しいのですが、どうでしょうか。現在でも URI.extract で

> 便利そうですね。私としては反対はありません。

んでは、コミットしちゃっていいですか?


> > [考えられる問題点]
> 
> >   * 括弧の数で (ユーザが) はまるかもしれない
> 
> たしかに。ドキュメントでカバー……と言いたいところなのですが
> 今のところドキュメントがないに等しい状況ですね。

添付のような感じでどうでしょう。

入るのなら日本語のほうも足しときます。
-------------------------------------------------------------------
青木峰郎

Index: lib/uri/common.rb
===================================================================
RCS file: /src/ruby/lib/uri/common.rb,v
retrieving revision 1.10
diff -u -p -r1.10 common.rb
--- lib/uri/common.rb	29 Mar 2003 06:39:50 -0000	1.10
+++ lib/uri/common.rb	7 Dec 2003 00:47:34 -0000
@@ -396,28 +396,46 @@ module URI
 --- URI::extract(str[, schemes])
 
 =end
-  def self.extract(str, schemes = [])
-    urls = []
-    regexp = ABS_URI_REF
-    unless schemes.empty?
-      regexp = Regexp.new('(?=' + schemes.collect{|s| 
-			    Regexp.quote(s + ':')
-			  }.join('|') + ')' + PATTERN::X_ABS_URI, 
-			  Regexp::EXTENDED, 'N')
+  def self.extract(str, schemes = nil, &block)
+    if block_given?
+      str.scan(regexp(schemes)) { yield $& }
+      nil
+    else
+      result = []
+      str.scan(regexp(schemes)) { result.push $& }
+      result
     end
+  end
+
+=begin
+
+--- URI::regexp([match_schemes])
+
+    Returns a Regexp object which matches to URI-like strings.
+    If MATCH_SCHEMES given, resulting regexp matches to URIs
+    whose scheme is one of the MATCH_SCHEMES.
 
-    str.scan(regexp) {
-      if block_given?
-	yield($&)
-      else
-	urls << $&
+    The Regexp object returned by this method includes arbitrary
+    number of capture group (parentheses).  Never rely on its
+    number.
+
+      # extract first URI from html_string
+      html_string.slice(URI.regexp)
+
+      # remove ftp URIs
+      html_string.sub(URI.regexp(['ftp'])
+
+      # You should not rely on the number of parentheses
+      html_string.scan(URI.regexp) do |*matches|
+        p $&
       end
-    }
 
-    if block_given?
-      return nil
+=end
+  def self.regexp(schemes = nil)
+    unless schemes
+      ABS_URI_REF
     else
-      return urls
+      /(?=#{Regexp.union(*schemes)}:)#{PATTERN::X_ABS_URI}/xn
     end
   end