これは、仕様に基づく、完全な URI 検証パターンの短縮バージョンです。これを書いたのは、Web 上で見つけたどの検証パターンにも含まれていない多くの文字が仕様で許可されているためです。ユーザー/パス (および 2 番目のパターンでは、パスとクエリ文字列) が、思ったよりもはるかに寛大であることがわかります。
/^(https?|ftp):\/\/(?# protocol
)(([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+(?# username
)(:([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+)?(?# password
)@)?(?# auth requires @
)((([a-z0-9][a-z0-9-]*[a-z0-9]\.)*(?# domain segments AND
)[a-z]{2}[a-z0-9-]*[a-z0-9](?# top level domain OR
)|(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5]\.){3}(?#
)(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])(?# IP address
))(:\d+)?(?# port
))\/?$/i
もう少し読みやすくするために時間をかけたので、ここに完全なパターンを示します。
/^(https?|ftp):\/\/(?# protocol
)(([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+(?# username
)(:([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+)?(?# password
)@)?(?# auth requires @
)((([a-z0-9][a-z0-9-]*[a-z0-9]\.)*(?# domain segments AND
)[a-z]{2}[a-z0-9-]*[a-z0-9](?# top level domain OR
)|(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5]\.){3}(?#
)(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])(?# IP address
))(:\d+)?(?# port
))(((\/+([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)*(?# path
)(\?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)(?# query string
)?)?)?(?# path and query string optional
)(#([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)?(?# fragment
)$/i
一部の (すべて?) JavaScript 実装は、正規表現でのコメントをサポートしていないことに注意してください。