2010-12-08 22 views
12

Estoy tratando de encontrar una solución confiable para extraer una url de una cadena de caracteres. Tengo un sitio donde los usuarios responden preguntas y en el cuadro de origen, donde ingresan su fuente de información, les dejo ingresar una url. Quiero extraer esa url y convertirla en un hipervínculo. Similar a cómo lo hace Yahoo Answers.Extracto URL de la cadena

¿Alguien conoce una solución confiable que pueda hacer esto?

Todas las soluciones que he encontrado funcionan para algunas URL, pero no para otras.

Gracias

Respuesta

22

John Gruber tiene spent a fair amount of time perfeccionar el "uno de expresiones regulares para gobernarlos a todos" para la detección de enlace. Usando preg_replace() como se menciona en las otras respuestas, utilizando el siguiente expresión regular debe ser uno de los más precisos, si no el más exacto, método para detectar un vínculo:

(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])) 

si sólo quería hacer coincidir HTTP/HTTPS:

(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])) 
+0

Exactamente lo que estaba buscando! Gracias. –

+4

Para cualquiera que quiera que todos los subpatrones convertidos no sean capturados, y el barras diagonales escapadas: \ b (?: (?: [az] [\ w -] +: (?: \/{1,3} | [a-z0-9%]) | www \ d {0,3 } [.] | [a-z0-9. \ -] + [.] [az] {2,4} \ /) (?: [^ \ s() <>] + | \ ((?: [^\ s() <>] + | (?: \ ([^^s() <>] + \))) * \)) + (?: \ ((?: [^ \ s() <> ] + | (?: \ ([^^s() <>] + \))) * \) | [^ \ s'!() \ [\] {} ;: '"., <>?« »" "''))) –

+0

Los TLD pueden tener mucho más de 4 caracteres, ver: http://www.iana.org/domains/root/db – Toto

0

Yahoo! Las respuestas hacen un buen trabajo de identificación del enlace cuando el enlace está escrito correctamente y separado de otro texto, pero no es muy bueno para separar la puntuación final. Por ejemplo, The links are http://example.com/somepage.php , http://example.com/somepage2.php , and http://example.com/somepage3.php . incluirá comas en los dos primeros y un período en el tercero.

Pero si eso es aceptable, entonces los patrones de este tipo debe hacerlo:

\<http:[^ ]+\> 

Parece que el analizador de stackoverflow es mejor. ¿Es de código abierto?

+0

inteligente, pero aún no es perfecto. echa de menos cosas como ssh + svn. – DampeS8N

3
$string = preg_replace('/https?:\/\/[^\s"<>]+/', '<a href="$0" target="_blank">$0</a>', $string); 

Solo coincide con http/https, pero ese es realmente el único protocolo que desea convertir en un enlace. Si quieres que los demás, se puede cambiar de esta manera:

$string = preg_replace('/(https?|ssh|ftp):\/\/[^\s"]+/', '<a href="$0" target="_blank">$0</a>', $string); 
+1

Es posible que también desee excluir '<' o aplicar 'htmlspecialchars' en la cadena coincidente para evitar la inyección de código. – Gumbo

+0

Bueno, pero si miras la expresión, permite cualquier cosa menos el espacio en blanco y '". Creo que eso elimina cualquier inyección de HTML. – Jonah

+1

Bron: No, estás usando el valor coincidente no solo como valor de atributo sino también como el contenido del texto de los elementos – Gumbo

-1

Este código me funcionó.

function makeLink($string){ 

/*** make sure there is an http:// on all URLs ***/ 
$string = preg_replace("/([^\w\/])(www\.[a-z0-9\-]+\.[a-z0-9\-]+)/i", "$1http://$2",$string); 
/*** make all URLs links ***/ 
$string = preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"_blank\" href=\"$1\">$1</a>",$string); 
/*** make all emails hot links ***/ 
$string = preg_replace("/([\w-?&;#~=\.\/]+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?))/i","<a href=\"mailto:$1\">$1</a>",$string); 

return $string; 
} 
+1

¿Por qué limita TLD a 3 caracteres? Eche un vistazo a: http://www.iana.org/domains/root/db – Toto

Cuestiones relacionadas