Я искал простой regex для URL, есть ли у кого-нибудь такой, который хорошо работает? Я не нашел такого в классах валидации zend framework и в других реализациях.
Ответ 1
Я использовал этот код в нескольких проектах, но я уверен, что это не исчерпывающий вариант:
$text = preg_replace(
'#((https?|ftp)://(\S*?\.\S*?))([\s)\[\]{},;"\':<]|\.\s|$)#i',
"'<a href=\"$1\" target=\"_blank\">$3</a>$4'",
$text
);
Большая часть случайного «кода» в конце — для решения таких ситуаций, как http://domain.com. в предложении (чтобы избежать совпадения с последующим периодом). Я уверен, что это можно убрать, но это работает.
Ответ 2
Используйте функцию filter_var() для проверки того, является ли строка URL или нет:
var_dump(filter_var('example.com', FILTER_VALIDATE_URL));
Использование регулярных выражений без необходимости — плохая практика.
Будьте осторожны, это решение не является юникод-безопасным и XSS-безопасным. Если вам нужна сложная валидация, возможно, лучше поискать другое решение.
Ответ 3На случай, если вы хотите узнать, существует ли URL на самом деле:
function url_exist($url){
$c=curl_init();
curl_setopt($c,CURLOPT_URL,$url);
curl_setopt($c,CURLOPT_HEADER,1); // получение заголовка
curl_setopt($c,CURLOPT_NOBODY,1); curl_setopt($c,CURLOPT_RETURNTRANSFER,1); // получить ответ в виде строки из curl_exec(), вместо того чтобы передавать его эхом
curl_setopt($c,CURLOPT_FRESH_CONNECT,1); // не использовать кэшированную версию урла
if(!curl_exec($c)){
//echo $url.' inexists';
return false;
}else{
//echo $url.' exists';
return true;
}
//$httpcode=curl_getinfo($c,CURLINFO_HTTP_CODE);
//return ($httpcode<400);
}
Ответ 4
Регулярное выражение:
(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s'!()\[\]{};:'\".,<>?«»“”'']))
использование в preg_match():
preg_match("/(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s'!()\[\]{};:'\".,<>?«»“”'']))/", $url)
Вот расширенный шаблон регулярного выражения (с комментариями):
(?xi)
\b
( # Захват 1: весь совпадающий URL
(?:
https?:// # http или https протокол
| # или
www\d{0,3}[.] # "www.", "www1.", "www2." … "www999."
| # или
[a-z0-9.\-]+[.][a-z]{2,4}/ # выглядит как доменное имя, за которым следует слэш )
(?: # варианты:
[^\s()<>]+ # не пробел и не-()<>
| # или
\(([^\s()<>]+|(\([^\s()<>]+\)))*\) # сбалансированные родительские элементы, до 2 уровней
)+
(?: # в конце:
\(([^\s()<>]+|(\([^\s()<>]+\)))*\) # сбалансированные родительские элементы, до 2 уровней
| # или
[^\s'!()\[\]{};:'".,<>?«»“”''] # не пробел или один из этих пунктуационных символов
)
)
Ответ 5
Я не думаю, что в данном случае разумно использовать регулярные выражения. Невозможно сопоставить все возможности, и даже если вы это сделали, все равно есть вероятность, что URL-адрес просто не существует.
Вот очень простой способ проверить, действительно ли URL существует и доступен для чтения:
if (preg_match("#^https?://.+#", $link) and @fopen($link,"r")) echo "OK";
Ответ 6
function validateURL($URL) {
$pattern_1 = "/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
$pattern_2 = "/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
if(preg_match($pattern_1, $URL) || preg_match($pattern_2, $URL)){
return true;
} else{
return false;
}
}
Ответ 7
Вот наиболее полное решение вашей проблемы.
function link_validate_url($text) {
$LINK_DOMAINS = 'aero|arpa|asia|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|local';
$LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array( // @TODO completing letters ...
"æ", // æ
"Æ", // Æ
"À", // À
"à", // à
"Á", // Á
"á", // á
"Â", // Â
"â", // â
"å", // å
"Å", // Å
"ä", // ä
"Ä", // Ä
"Ç", // Ç
"ç", // ç
"Ð", // Ð
"ð", // ð
"È", // È
"è", // è
"É", // É
"é", // é
"Ê", // Ê
"ê", // ê
"Ë", // Ë
"ë", // ë
"Î", // Î
"î", // î
"Ï", // Ï
"ï", // ï
"ø", // ø
"Ø", // Ø
"ö", // ö
"Ö", // Ö
"Ô", // Ô
"ô", // ô
"Õ", // Õ
"õ", // õ
"Œ", // Œ
"œ", // œ
"ü", // ü
"Ü", // Ü
"Ù", // Ù
"ù", // ù
"Û", // Û
"û", // û
"Ÿ", // Ÿ
"ÿ", // ÿ
"Ñ", // Ñ
"ñ", // ñ
"þ", // þ
"Þ", // Þ
"ý", // ý
"Ý", // Ý
"¿", // ¿
)), ENT_QUOTES, 'UTF-8');
$LINK_ICHARS = $LINK_ICHARS_DOMAIN . (string) html_entity_decode(implode("", array(
"ß", // ß
)), ENT_QUOTES, 'UTF-8');
$allowed_protocols = array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal');
// Начало группы скобок с (?: означает, что она сгруппирована, но не захвачена
$protocol = '((?:'. implode("|", $allowed_protocols) .'):\/\/)';
$authentication = "(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=" . $LINK_ICHARS . "]|%[0-9a-f]{2})+(?::(?:[\w". $LINK_ICHARS ."\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})*)?)?@)";
$domain = '(?:(?:[a-z0-9' . $LINK_ICHARS_DOMAIN . ']([a-z0-9'. $LINK_ICHARS_DOMAIN . '\-_\[\]])*)(\.(([a-z0-9' . $LINK_ICHARS_DOMAIN . '\-_\[\]])+\.)*('. $LINK_DOMAINS .'|[a-z]{2}))?)';
$ipv4 = '(?:[0-9]{1,3}(\.[0-9]{1,3}){3})';
$ipv6 = '(?:[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7})';
$port = '(?::([0-9]{1,5}))';
// Шаблон, специфичный для внешних ссылок.
$external_pattern = '/^'. $protocol .'?'. $authentication .'?('. $domain .'|'. $ipv4 .'|'. $ipv6 .' |localhost)'. $port .'?';
// Шаблон, специфичный для внутренних ссылок.
$internal_pattern = "/^(?:[a-z0-9". $LINK_ICHARS ."_\-+\[\]]+)";
$internal_pattern_file = "/^(?:[a-z0-9". $LINK_ICHARS ."_\-+\[\]\.]+)$/i";
$directories = "(?:\/[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'#!():;*@\[\]]*)*";
// Да, четыре обратных слеша == один обратный слеш.
$query = "(?:\/?\?([?a-z0-9". $LINK_ICHARS ."+_|\-\.~\/\\\\%=&,$'():;*@\[\]{} ]*))";
$anchor = "(?:#[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'():;*@\[\]\/\?]*)";
// Оставшаяся часть пути для стандартного URL.
$end = $directories .'?'. $query .'?'. $anchor .'?'.'$/i';
$message_id = '[^@].*@'. $domain;
$newsgroup_name = '(?:[0-9a-z+-]*\.)*[0-9a-z+-]*';
$news_pattern = '/^news:('. $newsgroup_name .'|'. $message_id .')$/i';
$user = '[a-zA-Z0-9'. $LINK_ICHARS .'_\-\.\+\^!#\$%&*+\/\=\?\'\|\{\}~\'\[\]]+';
$email_pattern = '/^mailto:'. $user .'@'.'(?:'. $domain .'|'. $ipv4 .'|'. $ipv6 .'|localhost)'. $query .'?$/';
if (strpos($text, '<front>') === 0) {
return false;
}
if (in_array('mailto', $allowed_protocols) && preg_match($email_pattern, $text)) {
return false;
}
if (in_array('news', $allowed_protocols) && preg_match($news_pattern, $text)) {
return false;
}
if (preg_match($internal_pattern . $end, $text)) {
return false;
}
if (preg_match($external_pattern . $end, $text)) {
return false;
}
if (preg_match($internal_pattern_file, $text)) {
return false;
}
return true;
}
Web