0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

なるだけシンプルにかつそれなりにちゃんと URL が抽出できる正規表現

Posted at

できるだけシンプルに。
[:space:] は正規表現エンジンの実装にあわせて全角スペースが含まれる奴に置き換えてください。

extract_url.rb
# !/usr/bin/env ruby
# -*- encoding: utf-8 -*-

URL_REGEXP = /((https?):\/\/(([^[:space:].\/]+\.)+[a-z]+)(\/[^[:space:]]*)?)/i

prefixes = ['', 'hoge', 'hoge ', 'ほげ ', '(']
suffixes = ['', ' fuga', ' fuga', ' ふが', ')']
patterns = [
  {url: 'http://example.com', scheme: 'http', domain: 'example.com', path: nil},
  {url: 'https://example.com', scheme: 'https', domain: 'example.com', path: nil},
  {url: 'http://example.com/', scheme: 'http', domain: 'example.com', path: '/'},
  {url: 'http://example.com/path/to/resource', scheme: 'http', domain: 'example.com', path: '/path/to/resource'},
  {url: 'http://example.com/index.html?foo=bar', scheme: 'http', domain: 'example.com', path: '/index.html?foo=bar'},
  {url: 'http://豊崎愛生.jp', scheme: 'http', domain: '豊崎愛生.jp', path: nil},
  {url: 'http://love.豊崎愛生.jp', scheme: 'http', domain: 'love.豊崎愛生.jp', path: nil},
  {url: 'http://love.豊崎愛生.jp/', scheme: 'http', domain: 'love.豊崎愛生.jp', path: '/'},
  {url: 'http://love.豊崎愛生.ジェーピー', unmatch: true},
  {url: 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット)', scheme: 'http', domain: 'ja.wikipedia.org', path: '/wiki/LISP_(声優ユニット)'},
]

prefixes.each do |prefix|
  suffixes.each do |suffix| 
    patterns.each do |pattern|
      test = "#{prefix}#{pattern[:url]}#{suffix}"
      ret = URL_REGEXP =~ test
      if !pattern[:unmatch] && ret
        {url: $1, scheme: $2, domain: $3, path: $5}.each do |k, v|
          s = pattern[k]
          puts "fail: [#{k}] '#{s}' -> '#{v}'" unless s == v
        end
      end
    end
  end
end

上のテストを走らせた時に失敗するパターン

out.txt
fail: [url] 'http://example.com/' -> 'http://example.com/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://example.com/path/to/resource' -> 'http://example.com/path/to/resource)'
fail: [path] '/path/to/resource' -> '/path/to/resource)'
fail: [url] 'http://example.com/index.html?foo=bar' -> 'http://example.com/index.html?foo=bar)'
fail: [path] '/index.html?foo=bar' -> '/index.html?foo=bar)'
fail: [url] 'http://love.豊崎愛生.jp/' -> 'http://love.豊崎愛生.jp/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット)' -> 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット))'
fail: [path] '/wiki/LISP_(声優ユニット)' -> '/wiki/LISP_(声優ユニット))'
fail: [url] 'http://example.com/' -> 'http://example.com/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://example.com/path/to/resource' -> 'http://example.com/path/to/resource)'
fail: [path] '/path/to/resource' -> '/path/to/resource)'
fail: [url] 'http://example.com/index.html?foo=bar' -> 'http://example.com/index.html?foo=bar)'
fail: [path] '/index.html?foo=bar' -> '/index.html?foo=bar)'
fail: [url] 'http://love.豊崎愛生.jp/' -> 'http://love.豊崎愛生.jp/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット)' -> 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット))'
fail: [path] '/wiki/LISP_(声優ユニット)' -> '/wiki/LISP_(声優ユニット))'
fail: [url] 'http://example.com/' -> 'http://example.com/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://example.com/path/to/resource' -> 'http://example.com/path/to/resource)'
fail: [path] '/path/to/resource' -> '/path/to/resource)'
fail: [url] 'http://example.com/index.html?foo=bar' -> 'http://example.com/index.html?foo=bar)'
fail: [path] '/index.html?foo=bar' -> '/index.html?foo=bar)'
fail: [url] 'http://love.豊崎愛生.jp/' -> 'http://love.豊崎愛生.jp/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット)' -> 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット))'
fail: [path] '/wiki/LISP_(声優ユニット)' -> '/wiki/LISP_(声優ユニット))'
fail: [url] 'http://example.com/' -> 'http://example.com/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://example.com/path/to/resource' -> 'http://example.com/path/to/resource)'
fail: [path] '/path/to/resource' -> '/path/to/resource)'
fail: [url] 'http://example.com/index.html?foo=bar' -> 'http://example.com/index.html?foo=bar)'
fail: [path] '/index.html?foo=bar' -> '/index.html?foo=bar)'
fail: [url] 'http://love.豊崎愛生.jp/' -> 'http://love.豊崎愛生.jp/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット)' -> 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット))'
fail: [path] '/wiki/LISP_(声優ユニット)' -> '/wiki/LISP_(声優ユニット))'
fail: [url] 'http://example.com/' -> 'http://example.com/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://example.com/path/to/resource' -> 'http://example.com/path/to/resource)'
fail: [path] '/path/to/resource' -> '/path/to/resource)'
fail: [url] 'http://example.com/index.html?foo=bar' -> 'http://example.com/index.html?foo=bar)'
fail: [path] '/index.html?foo=bar' -> '/index.html?foo=bar)'
fail: [url] 'http://love.豊崎愛生.jp/' -> 'http://love.豊崎愛生.jp/)'
fail: [path] '/' -> '/)'
fail: [url] 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット)' -> 'http://ja.wikipedia.org/wiki/LISP_(声優ユニット))'
fail: [path] '/wiki/LISP_(声優ユニット)' -> '/wiki/LISP_(声優ユニット))'

(http://ja.wikipedia.org/wiki/LISP_(声優ユニット))
(http://ja.wikipedia.org/wiki/LISP_(声優ユニット)}
(http://ja.wikipedia.org/wiki/LISP_(声優ユニット)))

(http://example.com/path/to/resource) みたいなことされるとどうしようもないので path の部分を (/[^[:space:]\(\)]*)? とかにするといけるようになりますが /wiki/LISP_(声優ユニット) とかがおかしくなります。
それも回避したい人はもっとがんばってください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?