Voici un design cependant: Par exemple, je mets un lien tel que
dans textarea. Comment obtenir PHP pour détecter qu’il s’agit d’un lien http://
et l’imprimer ensuite en tant que
print "<a href='http://www.example.com'>http://www.example.com</a>";
_ {Je me souviens d'avoir déjà fait quelque chose comme ça auparavant, cependant, ce n'était pas une preuve stupide qu'il continuait à casser pour des liens complexes.}
Une autre bonne idée serait si vous avez un lien tel que
http://example.com/test.php?val1=bla&val2blablabla%20bla%20bla.bl
corrige le pour qu'il le fasse
print "<a href='http://example.com/test.php?val1=bla&val2=bla%20bla%20bla.bla'>";
print "http://example.com/test.php";
print "</a>";
Celui-ci est juste un après la pensée .. stackoverflow pourrait également probablement l'utiliser aussi: D
Des idées
Regardons les exigences. Vous avez du texte brut fourni par l'utilisateur que vous souhaitez afficher avec des URL en hyperlien.
Edit: consultez Bitbucket pour la dernière version, avec prise en charge des adresses électroniques, des URL authentifiées, des URL entre guillemets et parenthèses, de la saisie HTML et d'une liste de TLD mise à jour.
Veuillez signaler les bogues et les demandes d'amélioration à l'aide de le suivi des problèmes de Bitbucket . Ils sont plus faciles à suivre de cette façon (et n'encombrent pas la zone de commentaire).} _
Voici ma prise:
<?php
$text = <<<EOD
Here are some URLs:
stackoverflow.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>";
Edit: le code suivant corrige les deux problèmes ci-dessus, mais est un peu plus détaillé puisque je suis plus ou moins en train de ré-implémenter preg_replace_callback
en utilisant 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)));
Voici quelque chose que j'ai trouvé qui est essayé et testé
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
);
}
Ça marche pour moi. Et cela fonctionne pour les emails et les URL, Désolé de répondre à ma propre question. :(
Mais celui-ci est le seul qui fonctionne
Voici le lien où je l'ai trouvé: http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_21878567.html
Sry à l'avance pour que ce soit un échange d'experts.
Vous parlez de moyens de faire avancer des choses complexes qui conviennent à certaines situations, mais nous avons surtout besoin d’une solution simple et négligente. Que diriez-vous simplement de cela?
preg_replace('/(http[s]{0,1}\:\/\/\S{4,})\s{0,}/ims', '<a href="$1" target="_blank">$1</a> ', $text_msg);
Essayez-le et laissez-moi savoir quelle URL folle il ne satisfait pas.
Voici le code utilisant les expressions rationnelles dans la fonction
<?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;
?>
J'utilise cette fonction, ça marche pour moi
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
Tous les crédits vont à - http://snipplr.com/view/68586/
Prendre plaisir!
Ce RegEx doit correspondre à n’importe quel lien, à l’exception de ces nouveaux domaines de niveau supérieur à plus de 3 caractères ...
{ \\ b # Faites correspondre la partie principale (proto: // nomhôte, ou simplement nomhôte) ( # http: // ou https: // partie principale (https?): // [- \\ w] + (\\. \\ w [- \\ w] *) + | # ou essayez de trouver un nom d’hôte avec une sous-expression plus spécifique (? i: [a-z0-9] (?: [: a-z0-9] * z0-9])? \\.) + # sous-domaines # Nous terminons maintenant avec .com, etc. Pour ceux-ci, utilisez minuscule (? -i: com \\ b | edu \\ b | biz \\ b | gov \\ b | in (?: t | fo) \\ b # .int ou .info | mil \\ b | net \\ b | org \\ b | [az] [az] \\. [az] [az] \\ b # code pays à deux lettres ) ) # Autoriser un numéro de port optionnel (: \\ d +)? # Le reste de l'URL est facultatif et commence par / ( / # Le reste est une heuristique pour ce qui semble bien fonctionner [^.!,?; "\\ '()\[\]\{\}\s\x7F - \\ xFF] * ( [.!,?] + [^.!,?; "\\ '() \\ [\\]\{\\}\s \\ x7F - \\ xFF ] + ) * )? } ix
Ce n'est pas écrit par moi, je ne sais pas trop d'où je viens, désolé de ne pouvoir donner aucun crédit ...
cela devrait vous donner des adresses email:
$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]
)
Comme je l'ai mentionné dans l'un des commentaires ci-dessus, mon VPS, qui exécute php 7, a démarré Émettant des avertissements Avertissement: preg_replace (): le modificateur/e n'est plus pris en charge, utilisez plutôt preg_replace_callback . Le tampon après le remplacement était vide/faux.
J'ai réécrit le code et apporté quelques améliorations ... Si vous pensez que vous devriez être dans la section auteur, n'hésitez pas à éditer le commentaire au-dessus de la fonction make_links_blank name . Je n'utilise pas intentionnellement le php de fermeture?> Pour évitez d'insérer des espaces dans la sortie.
<?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://stackoverflow.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;
}
}
Je sais que cette réponse a été acceptée et que cette question est assez ancienne, mais elle peut être utile pour d'autres personnes à la recherche d'autres implémentations.
Ceci est une version modifiée du code posté par: Angel.King.47 le 27 juillet 2009:
$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
);
Changements:
Comme l'a dit "Søren Løvborg", cette fonction n'échappe pas aux URL. J'ai essayé sa classe mais cela n'a pas fonctionné comme prévu (si vous ne faites pas confiance à vos utilisateurs, essayez d'abord son code).
Quelque chose dans le genre de:
<?php
if(preg_match('@^http://(.*)\s|$@g', $textarea_url, $matches)) {
echo '<a href=http://", $matches[1], '">', $matches[1], '</a>';
}
?>
Si vous voulez faire confiance à l'IANA, vous pouvez obtenir votre liste actuelle de TLD officiellement utilisés, tels que:
$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
La solution n ° 2 de Søren Løvborg est un peu moins explicite et vous évite les tracas de la mise à jour de la liste. Aujourd'hui, les nouveaux tld sont jetés si négligemment;)
Cela a fonctionné pour moi (transformé l'une des réponses en une fonction 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);
}
This class
change les URL en texte et en conservant l'URL d'origine telle qu'elle est J'espère que cela vous aidera et vous fera gagner du temps.
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);