php - una - Reemplazar las URL en el texto con enlaces HTML
href html ejemplos (15)
Algo como:
<?php
if(preg_match(''@^http://(.*)/s|$@g'', $textarea_url, $matches)) {
echo ''<a href=http://", $matches[1], ''">'', $matches[1], ''</a>'';
}
?>
Aquí hay un diseño: por ejemplo, puse un enlace como
en textarea . ¿Cómo obtengo PHP para detectar que es un enlace http://
y luego lo imprimo como
print "<a href=''http://www.example.com''>http://www.example.com</a>";
Recuerdo haber hecho algo como esto antes, sin embargo, no era una prueba infalible de que continuaba rompiendo enlaces complejos.
Otra buena idea sería si tienes un enlace como
http://example.com/test.php?val1=bla&val2blablabla%20bla%20bla.bl
arreglarlo así lo hace
print "<a href=''http://example.com/test.php?val1=bla&val2=bla%20bla%20bla.bla''>";
print "http://example.com/test.php";
print "</a>";
Este es solo un pensamiento posterior ... stackoverflow también podría usar esto también: D
Algunas ideas
Aquí hay algo que encontré que está probado y probado
function make_links_blank($text)
{
return preg_replace(
array(
''/(?(?=<a[^>]*>.+<//a>)
(?:<a[^>]*>.+<//a>)
|
([^="/']?)((?:https?|ftp|bf2|):////[^<> /n/r]+)
)/iex'',
''/<a([^>]*)target="?[^"/']+"?/i'',
''/<a([^>]+)>/i'',
''/(^|/s)(www.[^<> /n/r]+)/iex'',
''/(([_A-Za-z0-9-]+)(//.[_A-Za-z0-9-]+)*@([A-Za-z0-9-]+)
(//.[A-Za-z0-9-]+)*)/iex''
),
array(
"stripslashes((strlen(''//2'')>0?''//1<a href=/"//2/">//2</a>//3'':''//0''))",
''<a//1'',
''<a//1 target="_blank">'',
"stripslashes((strlen(''//2'')>0?''//1<a href=/"http:////2/">//2</a>//3'':''//0''))",
"stripslashes((strlen(''//2'')>0?''<a href=/"mailto://0/">//0</a>'':''//0''))"
),
$text
);
}
Esto funciona para mi. Y funciona para correos electrónicos y URL, siento contestar mi propia pregunta. :(
Pero este es el único que funciona
Aquí está el enlace donde lo encontré: http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_21878567.html
Sry de antemano por ser un intercambio de expertos.
Aunque es difícil hacer coincidir las especificaciones de la URL completa, esta es una expresión regular que generalmente hace un buen trabajo:
([/w-]+(/.[/w-]+)*@([a-z0-9-]+(/.[a-z0-9-]+)*?/.[a-z]{2,6}|(/d{1,3}/.){3}/d{1,3})(:/d{4})?)
Para utilizar esto en preg_replace, sin embargo, debe escapar. Como tal:
$pattern = "/([//w-]+(//.[//w-]+)*@([a-z0-9-]+(//.[a-z0-9-]+)*?//.[a-z]{2,6}|(//d{1,3}//.){3}//d{1,3})(://d{4})?)/";
$replaced_texttext = preg_replace($pattern, ''<a href="$0" title="$0">$0</a>'', $text);
Como mencioné en uno de los comentarios anteriores, mi VPS, que ejecuta php 7, comenzó a emitir advertencias Advertencia: preg_replace (): El modificador / e ya no es compatible, use preg_replace_callback en su lugar . El buffer después del reemplazo estaba vacío / falso.
He reescrito el código e hice algunas mejoras. Si crees que debes estar en la sección de autor, siéntete libre de editar el comentario sobre la función make_links_blank name. Intencionalmente no estoy usando el php?> De cierre para evitar insertar espacios en blanco en la salida.
<?php
class App_Updater_String_Util {
public static function get_default_link_attribs( $regex_matches = [] ) {
$t = '' target="_blank" '';
return $t;
}
/**
* App_Updater_String_Util::set_protocol();
* @param string $link
* @return string
*/
public static function set_protocol( $link ) {
if ( ! preg_match( ''#^https?#si'', $link ) ) {
$link = ''http://'' . $link;
}
return $link;
}
/**
* Goes through text and makes whatever text that look like a link an html link
* which opens in a new tab/window (by adding target attribute).
*
* Usage: App_Updater_String_Util::make_links_blank( $text );
*
* @param str $text
* @return str
* @see http://.com/questions/1188129/replace-urls-in-text-with-html-links
* @author Angel.King.47 | http://dashee.co.uk
* @author Svetoslav Marinov (Slavi) | http://orbisius.com
*/
public static function make_links_blank( $text ) {
$patterns = [
''#(?(?=<a[^>]*>.+?<//a>)
(?:<a[^>]*>.+<//a>)
|
([^="/']?)((?:https?|ftp):////[^<> /n/r]+)
)#six'' => function ( $matches ) {
$r1 = empty( $matches[1] ) ? '''' : $matches[1];
$r2 = empty( $matches[2] ) ? '''' : $matches[2];
$r3 = empty( $matches[3] ) ? '''' : $matches[3];
$r2 = empty( $r2 ) ? '''' : App_Updater_String_Util::set_protocol( $r2 );
$res = ! empty( $r2 ) ? "$r1<a href=/"$r2/">$r2</a>$r3" : $matches[0];
$res = stripslashes( $res );
return $res;
},
''#(^|/s)((?:https?://|www/.|https?://www/.)[^<>/ /n/r]+)#six'' => function ( $matches ) {
$r1 = empty( $matches[1] ) ? '''' : $matches[1];
$r2 = empty( $matches[2] ) ? '''' : $matches[2];
$r3 = empty( $matches[3] ) ? '''' : $matches[3];
$r2 = ! empty( $r2 ) ? App_Updater_String_Util::set_protocol( $r2 ) : '''';
$res = ! empty( $r2 ) ? "$r1<a href=/"$r2/">$r2</a>$r3" : $matches[0];
$res = stripslashes( $res );
return $res;
},
// Remove any target attribs (if any)
''#<a([^>]*)target="?[^"/']+"?#si'' => ''<a//1'',
// Put the target attrib
''#<a([^>]+)>#si'' => ''<a//1 target="_blank">'',
// Make emails clickable Mailto links
''/(([/w/-]+)(//.[/w/-]+)*@([/w/-]+)
(//.[/w/-]+)*)/six'' => function ( $matches ) {
$r = $matches[0];
$res = ! empty( $r ) ? "<a href=/"mailto:$r/">$r</a>" : $r;
$res = stripslashes( $res );
return $res;
},
];
foreach ( $patterns as $regex => $callback_or_replace ) {
if ( is_callable( $callback_or_replace ) ) {
$text = preg_replace_callback( $regex, $callback_or_replace, $text );
} else {
$text = preg_replace( $regex, $callback_or_replace, $text );
}
}
return $text;
}
}
Este RegEx debe coincidir con cualquier enlace a excepción de estos nuevos dominios de nivel superior de 3+ personajes ...
{ //b # Match the leading part (proto://hostname, or just hostname) ( # http://, or https:// leading part (https?)://[-//w]+(//.//w[-//w]*)+ | # or, try to find a hostname with more specific sub-expression (?i: [a-z0-9] (?:[-a-z0-9]*[a-z0-9])? //. )+ # sub domains # Now ending .com, etc. For these, require lowercase (?-i: com//b | edu//b | biz//b | gov//b | in(?:t|fo)//b # .int or .info | mil//b | net//b | org//b | [a-z][a-z]//.[a-z][a-z]//b # two-letter country code ) ) # Allow an optional port number ( : //d+ )? # The rest of the URL is optional, and begins with / ( / # The rest are heuristics for what seems to work well [^.!,?;"//'()/[/]/{/}/s/x7F-//xFF]* ( [.!,?]+ [^.!,?;"//'()//[//]/{//}/s//x7F-//xFF]+ )* )? }ix
No está escrito por mí, no estoy muy seguro de dónde lo obtuve, lo siento, no puedo dar crédito ...
Esto debería obtener su control de Twitter sin tocar su correo electrónico / (? <= ^ | (? <= [^ A-zA-Z0-9- .])) @ ([A-Za-z] + [A-Za] -z0-9 ] +) / i
Esto funcionó para mí (convirtió una de las respuestas en una función de PHP)
function make_urls_from_text ($text){
return preg_replace(''/(http[s]{0,1}/://///S{4,})/s{0,}/ims'', ''<a href="$1" target="_blank">$1 </a>'', $text);
}
He estado usando esta función, me funciona
function AutoLinkUrls($str,$popup = FALSE){
if (preg_match_all("#(^|/s|/()((http(s?)://)|(www/.))(/w+[^/s/)/<]+)#i", $str, $matches)){
$pop = ($popup == TRUE) ? " target=/"_blank/" " : "";
for ($i = 0; $i < count($matches[''0'']); $i++){
$period = '''';
if (preg_match("|/.$|", $matches[''6''][$i])){
$period = ''.'';
$matches[''6''][$i] = substr($matches[''6''][$i], 0, -1);
}
$str = str_replace($matches[''0''][$i],
$matches[''1''][$i].''<a href="http''.
$matches[''4''][$i].''://''.
$matches[''5''][$i].
$matches[''6''][$i].''"''.$pop.''>http''.
$matches[''4''][$i].''://''.
$matches[''5''][$i].
$matches[''6''][$i].''</a>''.
$period, $str);
}//end for
}//end if
return $str;
}//end AutoLinkUrls
Todos los créditos van a - http://snipplr.com/view/68586/
¡Disfrutar!
Sé que esta respuesta ha sido aceptada y que esta pregunta es bastante antigua, pero puede ser útil para otras personas que buscan otras implementaciones.
Esta es una versión modificada del código publicado por: Angel.King.47 el 27 de julio:
$text = preg_replace(
array(
''/(^|/s|>)(www.[^<> /n/r]+)/iex'',
''/(^|/s|>)([_A-Za-z0-9-]+(//.[A-Za-z]{2,3})?//.[A-Za-z]{2,4}///[^<> /n/r]+)/iex'',
''/(?(?=<a[^>]*>.+<//a>)(?:<a[^>]*>.+<//a>)|([^="/']?)((?:https?):////([^<> /n/r]+)))/iex''
),
array(
"stripslashes((strlen(''//2'')>0?''//1<a href=/"http:////2/" target=/"_blank/">//2</a> //3'':''//0''))",
"stripslashes((strlen(''//2'')>0?''//1<a href=/"http:////2/" target=/"_blank/">//2</a> //4'':''//0''))",
"stripslashes((strlen(''//2'')>0?''//1<a href=/"//2/" target=/"_blank/">//3</a> '':''//0''))",
),
$text
);
Cambios:
- Eliminé las reglas n. ° 2 y n. ° 3 (no estoy seguro de qué situaciones son útiles).
- Se eliminó el análisis del correo electrónico ya que realmente no lo necesito.
- Agregué una regla más que permite el reconocimiento de URL en la forma: [dominio] / * (sin www). Por ejemplo: "example.com/faq/" (Multiple tld: domain. {2-3}. {2-4} /)
- Al analizar cadenas que comienzan con "http: //", lo elimina de la etiqueta del enlace.
- Se agregó "target = ''_ blank''" a todos los enlaces.
- Las URL se pueden especificar justo después de cualquier etiqueta (?). Por ejemplo: <b> www.example.com </ b>
Como "Søren Løvborg" ha declarado, esta función no escapa a las URL. Intenté con su clase, pero simplemente no funcionó como esperaba (si no confías en tus usuarios, primero prueba su código).
Si desea confiar en la IANA, puede usar su lista actual de TLD apoyados oficialmente como:
$validTLDs =
explode("/n", file_get_contents(''http://data.iana.org/TLD/tlds-alpha-by-domain.txt'')); //get the official list of valid tlds
array_shift($validTLDs); //throw away first line containing meta data
array_pop($validTLDs); //throw away last element which is empty
Hace que la solución # 2 de Søren Løvborg sea un poco menos detallada y le ahorra la molestia de actualizar la lista, hoy en día los nuevos tlds se descartan tan descuidadamente;)
Ustedes están hablando de avances y cosas complejas que son buenas para algunas situaciones, pero sobre todo necesitamos una solución simple e imprudente. ¿Qué tal simplemente esto?
preg_replace(''/(http[s]{0,1}/://///S{4,})/s{0,}/ims'', ''<a href="$1" target="_blank">$1</a> '', $text_msg);
Pruébalo y cuéntame qué loca URL no satisface.
Veamos los requisitos. Tiene algún texto sin formato proporcionado por el usuario, que desea mostrar con URL hipervinculadas.
- El prefijo de protocolo "http: //" debe ser opcional.
- Ambos dominios y direcciones IP deben ser aceptados.
- Se debe aceptar cualquier dominio de nivel superior válido, por ejemplo .aero y .xn - jxalpdlp.
- Los números de puerto deberían estar permitidos.
- Las URL deben estar permitidas en contextos de oraciones normales. Por ejemplo, en "Visite .com.", El período final no es parte de la URL.
- Probablemente también quiera permitir las URL "https: //" y quizás otras también.
- Como siempre, al mostrar texto proporcionado por el usuario en HTML, desea evitar la creación de scripts de sitios cruzados (XSS). Además, querrá que los signos de unión en las URL se escapen correctamente como & amp ;.
- Probablemente no necesites soporte para direcciones IPv6.
- Editar : Como se señala en los comentarios, el soporte para las direcciones de correo electrónico es definitivamente una ventaja.
- Editar : solo se admite la entrada de texto sin formato: las etiquetas HTML en la entrada no se deben respetar. (La versión de Bitbucket admite entrada HTML).
Editar : Eche un vistazo a Bitbucket para obtener la última versión, con soporte para direcciones de correo electrónico, URL autenticadas, URL entre comillas y paréntesis, entrada de HTML, así como también una lista actualizada de TLD.
Por favor, informe errores y solicitudes de mejora con el rastreador de problemas de Bitbucket . Son más fáciles de rastrear de esa manera (y no saturan el área de comentarios).
Aquí está mi opinión:
<?php
$text = <<<EOD
Here are some URLs:
.com/questions/1188129/pregreplace-to-detect-html-php
Here''s the answer: http://www.google.com/search?rls=en&q=42&ie=utf-8&oe=utf-8&hl=en. What was the question?
A quick look at http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax is helpful.
There is no place like 127.0.0.1! Except maybe http://news.bbc.co.uk/1/hi/england/surrey/8168892.stm?
Ports: 192.168.0.1:8080, https://example.net:1234/.
Beware of Greeks bringing internationalized top-level domains: xn--hxajbheg2az3al.xn--jxalpdlp.
And remember.Nobody is perfect.
<script>alert(''Remember kids: Say no to XSS-attacks! Always HTML escape untrusted input!'');</script>
EOD;
$rexProtocol = ''(https?://)?'';
$rexDomain = ''((?:[-a-zA-Z0-9]{1,63}/.)+[-a-zA-Z0-9]{2,63}|(?:[0-9]{1,3}/.){3}[0-9]{1,3})'';
$rexPort = ''(:[0-9]{1,5})?'';
$rexPath = ''(/[!$-/0-9:;=@_/':;!a-zA-Z/x7f-/xff]*?)?'';
$rexQuery = ''(/?[!$-/0-9:;=@_/':;!a-zA-Z/x7f-/xff]+?)?'';
$rexFragment = ''(#[!$-/0-9:;=@_/':;!a-zA-Z/x7f-/xff]+?)?'';
// Solution 1:
function callback($match)
{
// Prepend http:// if no protocol specified
$completeUrl = $match[1] ? $match[0] : "http://{$match[0]}";
return ''<a href="'' . $completeUrl . ''">''
. $match[2] . $match[3] . $match[4] . ''</a>'';
}
print "<pre>";
print preg_replace_callback("&//b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:/"]?(/s|$))&",
''callback'', htmlspecialchars($text));
print "</pre>";
- Para escapar correctamente de los caracteres <y &, arrojo todo el texto a través de htmlspecialchars antes de procesarlo. Esto no es ideal, ya que el escape html puede causar una detección errónea de los límites de URL.
- Como lo demuestra el "Y recuerda. Nadie es perfecto". línea (en la que se recuerda. Nadie es tratado como una URL, debido al espacio faltante), es posible que sea necesario verificar en mayor detalle los dominios de nivel superior válidos.
Editar : El siguiente código corrige los dos problemas anteriores, pero es bastante más detallado ya que estoy implementando más o menos preg_replace_callback
usando preg_match
.
// Solution 2:
$validTlds = array_fill_keys(explode(" ", ".aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cu .cv .cx .cy .cz .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .yu .za .zm .zw .xn--0zwm56d .xn--11b5bs3a9aj6g .xn--80akhbyknj4f .xn--9t4b11yi5a .xn--deba0ad .xn--g6w251d .xn--hgbk6aj7f53bba .xn--hlcj6aya9esc7a .xn--jxalpdlp .xn--kgbechtv .xn--zckzah .arpa"), true);
$position = 0;
while (preg_match("{//b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:/"]?(/s|$))}", $text, &$match, PREG_OFFSET_CAPTURE, $position))
{
list($url, $urlPosition) = $match[0];
// Print the text leading up to the URL.
print(htmlspecialchars(substr($text, $position, $urlPosition - $position)));
$domain = $match[2][0];
$port = $match[3][0];
$path = $match[4][0];
// Check if the TLD is valid - or that $domain is an IP address.
$tld = strtolower(strrchr($domain, ''.''));
if (preg_match(''{/.[0-9]{1,3}}'', $tld) || isset($validTlds[$tld]))
{
// Prepend http:// if no protocol specified
$completeUrl = $match[1][0] ? $url : "http://$url";
// Print the hyperlink.
printf(''<a href="%s">%s</a>'', htmlspecialchars($completeUrl), htmlspecialchars("$domain$port$path"));
}
else
{
// Not a valid URL.
print(htmlspecialchars($url));
}
// Continue text parsing from after the URL.
$position = $urlPosition + strlen($url);
}
// Print the remainder of the text.
print(htmlspecialchars(substr($text, $position)));
esto debería obtener tus direcciones de correo electrónico:
$string = "bah bah [email protected] foo";
$match = preg_match(''/[^/x00-/x20()<>@,;://".[/]/x7f-/xff]+(?:/.[^/x00-/x20()<>@,;://".[/]/x7f-/xff]+)*/@[^/x00-/x20()<>@,;://".[/]/x7f-/xff]+(?:/.[^/x00-/x20()<>@,;://".[/]/x7f-/xff]+)+/'', $string, $array);
print_r($array);
// outputs:
Array
(
[0] => [email protected]
)
Aquí está el código usando expresiones regulares en función
<?php
//Function definations
function MakeUrls($str)
{
$find=array(''`((?:https?|ftp):///S+[[:alnum:]]/?)`si'',''`((?<!//)(www/./S+[[:alnum:]]/?))`si'');
$replace=array(''<a href="$1" target="_blank">$1</a>'', ''<a href="http://$1" target="_blank">$1</a>'');
return preg_replace($find,$replace,$str);
}
//Function testing
$str="www.cloudlibz.com";
$str=MakeUrls($str);
echo $str;
?>
Esta class
cambia las URL en texto y mientras mantiene la URL de inicio tal como está. Espero que esto ayude y ahorre tiempo para ti. Disfruta.
class RegClass
{
function preg_callback_url($matches)
{
//var_dump($matches);
//Get the matched URL text <a>text</a>
$text = $matches[2];
//Get the matched URL link <a href ="http://www.test.com">text</a>
$url = $matches[1];
if($url==''href ="http://www.test.com"''){
//replace all a tag as it is
return ''<a href=''.$url.'' rel="nofollow"> ''.$text.'' </a>'';
}else{
//replace all a tag to text
return " $text " ;
}
}
function ParseText($text){
$text = preg_replace( "/www/./", "http://www.", $text );
$regex ="/http:////http:////www/./"
$text = preg_replace( $regex, "http://www.", $text );
$regex2 = "/https:////http:////www/./";
$text = preg_replace( $regex2, "https://www.", $text );
return preg_replace_callback(''/<a/s(.+?)>(.+?)<//a>/is'',
array( &$this, ''preg_callback_url''), $text);
}
}
$regexp = new RegClass();
echo $regexp->ParseText($text);