Регулярное выражение для проверки индекса веб-сайта по сравнению с определенной страницей

#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 /?$