♪URI思い出の中に君をこのままURI閉じこめられない (c) 久保田利伸

IPv6にも対応したURIの正規表現とURIの各コンポーネントを取り出すスクリプト

RFC 3986とその更新版のRFC 6874で定められているIPv6や将来のIP(IPvFuture)も含めたURIと各コンポーネンツのシンタックスを1つの正規表現の中に閉じこめてみたよ!

/* * URI正規表現 * RFC3986とRFC6874に定められたURIシンタックスの正規表現 * Copyright (c) 2015 Kazz * http://asamuzak.jp * Dual licensed under MIT or GPL * http://asamuzak.jp/license */ /^([a-z][a-z0-9\+\-\.]*):(?:\/\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*@)?(\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*)(:[0-9]*)?((?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)|(\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)?|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2}){0}))(\?(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*)?(#(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*)?$/i

URIなので、http(s):やftp:だけでなく、mailto:とかtel:とかurn:とかでも使えます。

URIとしての書式の妥当性を検証しURIの各コンポーネントを取り出すツール

URI正規表現チェッカー
URIを入力
URIを検証
Valid
URI
Scheme
Host
Port
Path
Query
Fragment

JavaScriptソース (最終更新:2015/6/17)

URI正規表現チェッカーでも使っている関数のソースです。

  • getUriComponents('http://example.com')のように検証したいURIの文字列を渡してください
  • 戻り値の型はObjectです
  • 戻り値はプロパティーとしてvalid、uri、scheme、host、port、path、query、fragmentを持っています
  • validには真偽値、それ以外のプロパティーには文字列が入っています(未検出の場合は空文字)
  • portは':80'、queryは'?key'、fragmentは'#id'などそれぞれデリミターもついています

/**
*   getUriComponents()
*   URI文字列を検証しURIの各コンポーネントを取得
*   Copyright (c) 2015 Kazz
*   http://asamuzak.jp
*   Dual licensed under MIT or GPL
*   http://asamuzak.jp/license
*/

function isType(o, t) {
    var x = o && Object.prototype.toString.call(o).slice(8, -1);
    return o && (t ? new RegExp('^' + t + '$', 'i').test(x) : x);
}
function getUriComponents(u) {
    var x = { valid: null, uri: '', scheme: '', host: '', port: '', path: '', query: '', fragment: '' }, y, z, i, l;
    if(isType(u, 'String')) {
        y = u.match(/^([a-z][a-z0-9\+\-\.]*):(?:\/\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*@)?(\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*)(:[0-9]*)?((?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)|(\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)?|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2}){0}))(\?(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*)?(#(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*)?$/i);
        if(y) {
            u = /^[a-z][a-z0-9\+\-\.]*:[\/]{2}/.test(u);
            x.valid = true;
            for(i = 0, l = y.length; i < l; i++) {
                z = y[i];
                if(z) {
                    switch(i) {
                        case 0:
                            x.uri = z; break;
                        case 1:
                            x.scheme = z; break;
                        case 2:
                            u && (x.host = z); break;
                        case 3:
                            u && (x.port = z); break;
                        case 4:
                            u && (x.path = z); break;
                        case 5:
                            x.path = z; break;
                        case 6:
                            x.query = z; break;
                        case 7:
                            x.fragment = z; break;
                    }
                }
            }
        }
        else {
            x.valid = false;
        }
    }
    else {
        x.valid = false;
    }
    return x;
}

URIのABNF記法とその正規表現への変換例

reserved = gen-delims / sub-delims
[:\/\?\#\[\]@!\$&'\(\)\*\+,;=]
gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
[:\/\?\#\[\]@]
sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
[!\$&'\(\)\*\+,;=]
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
[a-z0-9\-\._~]
pct-encoded = "%" HEXDIG HEXDIG
%[0-9A-F]{2}
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
scheme host port path query fragmentはキャプチャ ^([a-z][a-z0-9\+\-\.]*):(?:\/\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*@)?(\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*)(:[0-9]*)?((?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)|(\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)?|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2}){0}))(\?(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*)?(#(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*)?$
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
[a-z][a-z0-9\+\-\.]*
hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty
\/\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*@)?(?:\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*)(?::[0-9]*)?(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*| \/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)?| (?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)* (?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2}){0} 最適化(host port pathはキャプチャ) (?:\/\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*@)?(\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*)(?::([0-9]*))?((?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)|(?:\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)?|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2}){0}))
authority = [ userinfo "@" ] host [ ":" port ]
(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*@)?(?:\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*)(?::[0-9]*)?
userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]|%[0-9A-F]{2})*
host = IP-literal / IPv4address / reg-name
\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*
port = *DIGIT
[0-9]*
IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]"
\[(?:(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+|(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::|v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+)\]
ZoneID = 1*( unreserved / pct-encoded )
(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+
IPv6addrz = IPv6address "%25" ZoneID
(?:(?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)%25(?:[a-z0-9\-\._~]|%[0-9A-F]{2})+
IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
v[0-9a-f]+\.[a-z0-9\-\._~!\$&'\(\)\*\+,;=:]+
IPv6address = 6( h16 ":" ) ls32 / "::" 5( h16 ":" ) ls32 / [ h16 ] "::" 4( h16 ":" ) ls32 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 / [ *4( h16 ":" ) h16 ] "::" ls32 / [ *5( h16 ":" ) h16 ] "::" h16 / [ *6( h16 ":" ) h16 ] "::"
(?:[0-9a-f]{1,4}:){6}(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| ::(?:[0-9a-f]{1,4}:){5}(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| [0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| (?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| (?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| (?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| (?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.)(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})| (?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}| (?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?:: 最適化 (?:(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|[0-9a-f]{1,4}?::(?:[0-9a-f]{1,4}:){4}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4}:){6})(?:(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))|[0-9a-f]{1,4}:[0-9a-f]{1,4})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::
h16 = 1*4HEXDIG
[0-9a-f]{1,4}
ls32 = ( h16 ":" h16 ) / IPv4address
[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))
IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
(?:(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))\.){3}(?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))
dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35
[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5] 最適化 (?:(?:1[0-9]|[1-9])?[0-9]|2(?:[0-4][0-9]|5[0-5]))
reg-name = *( unreserved / pct-encoded / sub-delims )
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=]|%[0-9A-F]{2})*
path-abempty = *( "/" segment )
(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*
path-absolute = "/" [ segment-nz *( "/" segment ) ]
\/(?:(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*)?
path-rootless = segment-nz *( "/" segment )
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+(?:\/(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*)*
path-empty = 0<pchar>
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2}){0}
segment = *pchar
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})*
segment-nz = 1*pchar
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@]|%[0-9A-F]{2})+
query = *( pchar / "/" / "?" )
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*
fragment = *( pchar / "/" / "?" )
(?:[a-z0-9\-\._~!\$&'\(\)\*\+,;=:@\/\?]|%[0-9A-F]{2})*

正規表現は基本的に脳内変換と手書きです。 たぶん間違ってないとは思いますが確証はありませんorz

最適化には正規表現あせんぶるちゃんを使いました。 有用なツールを公開いただき多謝です!

"♪URI思い出の中に君をこのままURI閉じこめられない (c) 久保田利伸"へのTwitter上でのコメントやRT

6件のツイートがあります。

ツイート 1

ツイート 2

ツイート 3

ツイート 4

ツイート 5

ツイート 6