PHP - Különböző formátumú url és email címek lecserélése

PHP - Különböző formátumú url és email címek lecserélése
2018-10-02T16:04:28+02:00
2018-10-04T09:15:21+02:00
2022-10-15T21:31:11+02:00
Prog Tan
Sziasztok!

A preg_replace() függvénnyel egyetlen regexp megfogalmazással szeretném az alábbi link formátumokat kattintható linkké átalakítani, lecserélni.

http://domainnev.com
https://domainnev.org
domainnev.de
www.domainnev.fr
https://www.domainnev.cz
nev@domainnev.hu

Valami ehhez hasonló módon:

preg_replace('"\b(https?://\S+)"','<a href="$1" target="_blank">$1</a>',$string);
Az fontos, hogy az email címeket is bele szeretném fogalmazni, amely ilyesmi alakba cserélődne le!

<a href="mailto:$1">$1</a>
Ezeket meg lehet oldani egyetlen egy regexp-el?
Tudtok segíteni a megfogalmazásában?

Köszönöm szépen!
Mutasd a teljes hozzászólást!
Hali!

Tökéletes megoldás – szerintem – nincs erre a problémára, fogsz kapni téves találatokat is (gondolj csak pl. arra az esetre, amikor a mondatvégi pont után nem raksz ki szóközt, amit egy min. két karakteres mondatkezdő szó követ, nem kellő karakterek követik az URL-t, stb.).

Egy reguláris kifejezéssel ugyan le lehet „fedni” mind a normál URL-eket, mind az e-mail címeket, de preg_replace()-szel cserélni különböző módon azokat már nem lehet. De semmi gond, hiszen ott van a preg_replace_callback(). Megfelelően megalkotott reguláris kifejezéssel megoldható a feladat.
A következő reguláris kifejezés nagyjából lefedi az összes lehetőséget (persze, nem hibamentes – teszteld és alakítsd tovább az igényeid szerint):
/(?: (?<!\S@)(?<scheme>(?:[a-z]+:)?\/\/(?:\S+@)?)?\b(?<urldomain>(?:(?=[a-z0-9-]{1,63}\.)(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,63})(?!@)(?<path>\/\S*)*\b | (?<user>[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@)(?<emaildomain>(?:(?=[a-z0-9-]{1,63}\.)(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,63})\b )/ix
A következő módon dolgozhatod pl. fel:
$text = '...'; // Feldolgozandó szöveg $pattern = '...'; // A fenti reguláris kifejezés $newText = preg_replace_callback($pattern, function($m) { if (isset($m['emaildomain'])) { return '<a href="mailto:'.$m[0].'">'.$m[0].'</a>'; } else { return '<a href="'.($m['scheme'] == '' ? '//' : '').$m[0].'" target="_blank">'.$m[0].'</a>'; } }, $text); echo $newText;
Annyit változtattam a nyitó hozzászólásodban leírt igényeden, hogy ha séma (vagy //) nélküli az URL, akkor elé rakok '//'-t.

Megnézheted „működés közben”: PHP Sandbox.

Mutasd a teljes hozzászólást!

  • Esetleg valaki tud segíteni a regexp megfogalmazásában?
    Mutasd a teljes hozzászólást!
  • Lehet, hogy ezt szeretnéd, melyből már készíthetsz email címet?
    Ha tévedtem sorry...
    Mutasd a teljes hozzászólást!
  • Sajnos a belinkelt oldalon nem találtam meg, amit keresek.

    A fenti példáimból kiindulva az alábbi módon szeretném átalakítani az url és email címeket.

    http://domainnev.com => <a href="http://domainnev.com" target="_blank">http://domainnev.com</a> https://domainnev.org => <a href="https://domainnev.org" target="_blank">https://domainnev.org</a> domainnev.de => <a href="http://domainnev.de" target="_blank">http://domainnev.de</a> www.domainnev.fr => <a href="http://www.domainnev.fr" target="_blank">http://www.domainnev.fr</a> https://www.domainnev.cz => <a href="https://www.domainnev.cz" target="_blank">https://www.domainnev.cz</a> nev@domainnev.hu => <a href="mailto:nev@domainnev.hu">nev@domainnev.hu</a>
    Ezt miképpen lehetne egyetlen regexp-el megoldani preg_replace() függvény segítségével?
    Megoldható?
    Mutasd a teljes hozzászólást!
  • És simán összefűzéssel nem menne? ->

    <?php $cim = array('http://domainnev.com', 'https://domainnev.org', 'domainnev.de', 'www.domainnev.fr', 'https://www.domainnev.cz', 'nev@domainnev.hu' ); for( $i=0;$i<count($cim);$i++ ) { // IF & ELSE echo '<a href="'.$cim[$i].'" target="_blank">'.$cim[$i].'</a><br>'; } ?>
    Bár lehet, hogy még mindig félreértem a kérdésed...
    Megj: Az emailes lehetőség miatt pedig egy IF ELSE az alapján, hogy van-e a tömbelemben @ karakter és másik vizsgálat van-e az elején valahol :// ...
    Mutasd a teljes hozzászólást!
  • Köszönöm a tippet!

    A fenti 6 cím csak egy-egy példa a különböző címformátumokra.

    Nem ezt a konkrét 6 darab címet szeretném átalakítani linkké, hanem az adott szövegben ha szerepel ilyen formátumú/szerkezetű/kinézetű cím, akkor azt cserélje le kattintható linkre.
    Remélem, így már érthető, amit szeretnék.
    Mutasd a teljes hozzászólást!
  • Akkor esetleg nézd meg ezt a link-et, hátha találsz megfelelő függvényt.
    Kérdés: És mi lenne a keresési feltétel ha a "domainnev.de" első és második eleme is lehet bármi, sőt lehet előtte http vagy https vagy www stb sőt lehe email is @-al?
    Mutasd a teljes hozzászólást!
  • Akkor már a //domainnev.tld -t is vedd listára

    Egy RegEx -el nem fog menni, mindenképp többel kell megoldani,
    és ügyelve, hogy ne legyen linkhalmozás.

    Aztán ha ez meg van jöhet az XSS szűrés
    $string = 'http://pog.hu/"><script>alert("Hopp...");</script>';
    Vagy pl.
    $string = 'http://prog.hu/"onmouseover=alert("Hopp...");';
    Mutasd a teljes hozzászólást!
  • Lehet, hogy le van mentve az összes lehetséges variáció, csak titok...
    Mutasd a teljes hozzászólást!
  • Hali!

    Tökéletes megoldás – szerintem – nincs erre a problémára, fogsz kapni téves találatokat is (gondolj csak pl. arra az esetre, amikor a mondatvégi pont után nem raksz ki szóközt, amit egy min. két karakteres mondatkezdő szó követ, nem kellő karakterek követik az URL-t, stb.).

    Egy reguláris kifejezéssel ugyan le lehet „fedni” mind a normál URL-eket, mind az e-mail címeket, de preg_replace()-szel cserélni különböző módon azokat már nem lehet. De semmi gond, hiszen ott van a preg_replace_callback(). Megfelelően megalkotott reguláris kifejezéssel megoldható a feladat.
    A következő reguláris kifejezés nagyjából lefedi az összes lehetőséget (persze, nem hibamentes – teszteld és alakítsd tovább az igényeid szerint):
    /(?: (?<!\S@)(?<scheme>(?:[a-z]+:)?\/\/(?:\S+@)?)?\b(?<urldomain>(?:(?=[a-z0-9-]{1,63}\.)(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,63})(?!@)(?<path>\/\S*)*\b | (?<user>[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@)(?<emaildomain>(?:(?=[a-z0-9-]{1,63}\.)(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z]{2,63})\b )/ix
    A következő módon dolgozhatod pl. fel:
    $text = '...'; // Feldolgozandó szöveg $pattern = '...'; // A fenti reguláris kifejezés $newText = preg_replace_callback($pattern, function($m) { if (isset($m['emaildomain'])) { return '<a href="mailto:'.$m[0].'">'.$m[0].'</a>'; } else { return '<a href="'.($m['scheme'] == '' ? '//' : '').$m[0].'" target="_blank">'.$m[0].'</a>'; } }, $text); echo $newText;
    Annyit változtattam a nyitó hozzászólásodban leírt igényeden, hogy ha séma (vagy //) nélküli az URL, akkor elé rakok '//'-t.

    Megnézheted „működés közben”: PHP Sandbox.

    Mutasd a teljes hozzászólást!
  • mondatvégi pont után nem raksz ki szóközt, amit egy min. két karakteres mondatkezdő szó követ, nem kellő karakterek követik az URL-t, stb

    Jogos!

    Ettől függetlenül s nagyon szépen köszönöm a kódodat! Lefedi azt, amit szerettem volna.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd