♪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の各コンポーネントを取り出すツール
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
asamuzaK.jp : ♪URI思い出の中に君をこのままURI閉じこめられない (c)久保田利伸 ~ URIのシンタックスにマッチする正規表現とURIの各コンポーネントを取り出すスクリプト http://t.co/VfbSY75Uiq
ツイート 2
正規表現はiフラグをつけるよう変更 RFC 3986 3.2.2での指摘を正規表現にも落とし込んでみた 英字は[a-z]、HEXは[0-9a-f]、%HEX HEXだけは%[0-9A-Z]{2} …iフラグつけてるから効果はないけどw http://t.co/VfbSY75Uiq
ツイート 3
あ、ZoneIDの正規表現間違ってる…orz *じゃなくて+だ あとでなおそう asamuzaK.jp : ♪URI思い出の中に君をこのままURI閉じこめられない (c) 久保田利伸 http://t.co/VfbSY75Uiq
ツイート 4
前にこんなの作りました お役に立てば https://t.co/VfbSY75Uiq https://t.co/mJQSJh9d1G
ツイート 5
あれ? いつの間にか、正規表現あせんぶるちゃんがデッドリンクだ… 便利だったのになぁ… asamuzaK.jp : ♪URI思い出の中に君をこのままURI閉じこめられない (c) 久保田利伸 https://t.co/VfbSY75Uiq
ツイート 6
あ、バグ発見… asamuzaK.jp : ♪URI思い出の中に君をこのままURI閉じこめられない (c) 久保田利伸 https://t.co/VfbSY75Uiq