$re = '/
# allow multiple groups with the same name
(?J)
# protocol user host-ip port path path path querystring fragment
^
#protocol
(?:(?<scheme>[a-zA-Z][a-zA-Z\d+-.]*):)?
(?|
#slash-slash
\/\/
#userinfo
(?:
#user
(?<user>[a-zA-Z\d\-._~\!$&\'()*+,;=%]*)
#password
(?::(?<pass>[a-zA-Z\d\-._~\!$&\'()*+,;=:%]*))?
@)?
#host-ip
(?<host>(?:[a-zA-Z\d-.%]+)|(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:\[(?:[a-fA-F\d.:]+)\]))?
#port
(?::(?<port>\d*))?
#slash-path
(?<path>
(?:\/ [a-zA-Z\d\-._~\!$&\'()*+,;=:@%]* )*
)
#slash-path
|(?<user>)(?<pass>)(?<host>)(?<port>)
(?<path>\/ [a-zA-Z\d\-._~\!$&\'()*+,;=:@%]+(?:\/[a-zA-Z\d\-._~\!$&\'()*+,;=:@%]*)*)?
#path
|(?<user>)(?<pass>)(?<host>)(?<port>)
(?<path> [a-zA-Z\d\-._~\!$&\'()*+,;=:@%]+(?:\/[a-zA-Z\d\-._~\!$&\'()*+,;=:@%]*)*)
)?
#querystring
(?:\?(?<query>[a-zA-Z\d\-._~\!$&\'()*+,;=:@%\/?]*))?
#fragment
(?:\#(?<fragment>[a-zA-Z\d\-._~\!$&\'()*+,;=:@%\/?]*))?
$
/xm';
$str = 'https://regex101.com/
https://regex101.com/thing/blah.foo
https://regex101.com:28801/thing/blah/patterns?where_foo=bar&where_primary_access_node=true
https://regex101.com:8443/thing/index.html#/landing';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the entire match result
var_dump($matches);
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for PHP, please visit: http://php.net/manual/en/ref.pcre.php