#regex #url
Вопрос:
Я ищу регулярное выражение, которое позволит мне проверить, является ли строка ссылкой на адрес веб-сайта или конкретной страницей на этом веб-сайте.
Так что это соответствовало бы:
http://google.com
ftp://google.com
http://google.com/
http://lots.of.subdomains.google.com
Но не:
http://google.com/search.whatever
ftp://google.com/search.whatever
http://lots.of.subdomains.google.com/search.whatever
Есть какие-нибудь идеи? Я не совсем понимаю, как справиться с разрешением /
в конце URL-адреса.
Ответ №1:
Попробуй это:
(http|ftp|https)://([a-zA-Z0-9-.] )/?
Комментарии:
1. Помните, что если вы используете php для экранирования «/» или регулярное выражение не будет компилироваться 🙂
2. Спасибо, Джереми! Это делает свое дело. @LaQuet — На самом деле я использую это в javascript, но спасибо за предупреждение.
Ответ №2:
Это сокращенная версия моего полного шаблона проверки URI, основанного на спецификации. Я написал это, потому что спецификация допускает множество символов, никогда не включенных ни в один шаблон проверки, который я нашел в Интернете. Вы увидите, что пользователь/пропуск (и во втором шаблоне, путь и строка запроса) гораздо более разрешительны, чем вы думали.
/^(https?|ftp)://(?# protocol
)(([a-z0-9$_. !*'(),;?amp;=-]|%[0-9a-f]{2}) (?# username
)(:([a-z0-9$_. !*'(),;?amp;=-]|%[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|1d{2}|2[0-4][0-9]|25[0-5].){3}(?#
)(d|[1-9]d|1d{2}|2[0-4][0-9]|25[0-5])(?# IP address
))(:d )?(?# port
))/?$/i
И поскольку я потратил время на то, чтобы сделать это несколько более читабельным, вот полная схема:
/^(https?|ftp)://(?# protocol
)(([a-z0-9$_. !*'(),;?amp;=-]|%[0-9a-f]{2}) (?# username
)(:([a-z0-9$_. !*'(),;?amp;=-]|%[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|1d{2}|2[0-4][0-9]|25[0-5].){3}(?#
)(d|[1-9]d|1d{2}|2[0-4][0-9]|25[0-5])(?# IP address
))(:d )?(?# port
))(((/ ([a-z0-9$_. !*'(),;:@amp;=-]|%[0-9a-f]{2})*)*(?# path
)(?([a-z0-9$_. !*'(),;:@amp;=-]|%[0-9a-f]{2})*)(?# query string
)?)?)?(?# path and query string optional
)(#([a-z0-9$_. !*'(),;:@amp;=-]|%[0-9a-f]{2})*)?(?# fragment
)$/i
Обратите внимание, что некоторые (все?) реализации javascript не поддерживают комментарии в регулярных выражениях.
Комментарии:
1. Вау, спасибо за выдающийся ответ. Я думаю, что для меня это излишне — я использую это регулярное выражение скорее как предупреждение пользователю, чем как требование, поэтому я предпочитаю простую версию. Но это, безусловно, выдающийся ресурс.
2. Я ценю ваши добрые слова. Мне любопытно, почему вы выбрали менее способного? Во всяком случае, помимо того, что он написан в соответствии со спецификацией, он также позволяет использовать IP-адреса и порты, ни один из которых не является чем-то необычным для URL-адресов, отправленных пользователем.
Ответ №3:
Отличный ответ от Джереми. В зависимости от того, какой диалект регулярного выражения вы используете для сопоставления, вы можете обернуть все выражение якорями (чтобы избежать совпадения URL-адресов, например http://example.com/bin/cgi?returnUrl=http://google.com
) и, возможно, обобщить допустимые символы протокола и доменного имени:
^w ://(w .) w /?$