Ruby で URL から正規表現で各種文字列(ファイル名など)を抽出する

大前提

正規表現は最後の手段にするべきです。

結論

RFC3986 に従います(後述)。

たとえば対象とする URL が https://pbs.twimg.com/media/FAlJ_JsUUAAgOSq?format=jpg&name=orig であったとします。そのとき、以下のように抽出できます。

url = 'https://pbs.twimg.com/media/FAlJ_JsUUAAgOSq?format=jpg&name=orig'

/\A(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?\Z/.match(url)

実行結果

実行結果は以下のようになります。

pry(main)> /\A(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?\Z/.match(url)
=> #<MatchData
 "https://pbs.twimg.com/media/FAlJ_JsUUAAgOSq?format=jpg&name=orig"
 1:"https:"
 2:"https"
 3:"//pbs.twimg.com"
 4:"pbs.twimg.com"
 5:"/media/FAlJ_JsUUAAgOSq"
 6:"?format=jpg&name=orig"
 7:"format=jpg&name=orig"
 8:nil
 9:nil>

今回 nil となっている 89 の値には「フラグメント(ハッシュ)」が入ります。https://example.com/foobar#hoge#hoge に当たる部分です。

この例の場合には 8 には #hoge が、9 には hoge が入ります。

背景

RFC3986 に書かれている正規表現をそのまま Ruby で書きました。 datatracker.ietf.org

(補足)ファイル名を取得する場合

ファイル名を取得するには 5 の値を File.basename メソッドに渡します。

url = 'https://pbs.twimg.com/media/FAlJ_JsUUAAgOSq.jpg'
url_path = /\A(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?\Z/.match(url)[5]

File.basename(url_path) #=> "FAlJ_JsUUAAgOSq.jpg"
Powered by はてなブログ