[PHP] preg_replace url hyperlinken

Pagina: 1
Acties:
  • 239 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
Ok, ik ben al een tijdje bezig om een nieuwssysteempje wat ik 2 jaar geleden in elkaar gezet heb te verbeteren en uit te breiden. Natuurlijk zitten er de standaard bb-codes in, onder andere om een url te plaatsen. Dit gaat allemaal goed. Nu wil ik ook dat url's zonder de [ url ] bbcode automatisch worden gehyperlinked.

stel, user post deze code:
code:
1
2
3
[url=www.google.nl]klik hier![/url]
[url]www.google.com[/url]
www.google.be


daar komt dan nu het volgende uit:
code:
1
2
3
<a href="<a href="http://www.google.nl title="http://www.google.nl">www.google.nl</a> target="_blank">klik hier!</a>
<a href="<a href="http://www.google.com title="http://www.google.com">www.google.com</a> target="_blank"><a href="http://www.google.com</a>" title="www.google.com</a>">www.google.com</a>
<a href="http://www.google.be" title="www.google.be">www.google.be</a>


Er is dus iets mis met de preg_replace die de url's die nog niet gehyperlinked zijn op het laatst vervangt. Ik heb al gezocht, en verschillende voorbeelden hier gevonden, maar het is telkens nét niet wat ik hebben moet. Op dit moment heb ik de volgende preg_replace om te hyperlinken:

code:
1
$message = preg_replace("`(?<!<a href=)((http)+(s)?:(//)|(www\.))((\w|\.|\-|_)+)(/)?(\S+)?`i", "<a href=\"http\\3://\\5\\6\\8\\9\" title=\"\\0\">\\5\\6</a>", $message);


Misschien dat een regex-guru ziet wat er mis is, want ik zit echt al sinds gister naar die regel te staren :)

edit:
De HTML waar deze regex overheen gaat is dus het volgende:
code:
1
2
3
<a href="http://www.google.nl" target="_blank">klik hier!</a>
<a href="http://www.google.com" target="_blank">www.google.com</a>
www.google.be

[ Voor 43% gewijzigd door kauwgomballen op 22-06-2005 14:37 ]


Acties:
  • 0 Henk 'm!

  • compufreak88
  • Registratie: November 2001
  • Laatst online: 02-05 17:51
Er was hier laatst een programmaatje dat heette regexcoach ofzoiets. Ik denk dat die hier wel handig voor is...

Acties:
  • 0 Henk 'm!

Verwijderd

Je moet eerst de UBB-code parsen. Dan kun je met onderstaande RegExp alle niet-subdomein-url's omzetten:

/\b(?:www|http://www)\.([^\.]+\.\w{2,3}(?:\?[\w\d=&_-]+)?)\b/http://www.$1/ig

De RegExp voor subdomeinen post ik straks.

[ Voor 74% gewijzigd door Verwijderd op 22-06-2005 14:58 ]


Acties:
  • 0 Henk 'm!

  • Schonhose
  • Registratie: April 2000
  • Laatst online: 17-09 20:01

Schonhose

Retro Icoon

compufreak88 schreef op woensdag 22 juni 2005 @ 14:19:
Er was hier laatst een programmaatje dat heette regexcoach ofzoiets. Ik denk dat die hier wel handig voor is...
The Regex Coach - interactive regular expressions

"The thing under my bed waiting to grab my ankle isn't real. I know that, and I also know that if I'm careful to keep my foot under the covers, it will never be able to grab my ankle." - Stephen King
Quinta: 3 januari 2005


Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
Verwijderd schreef op woensdag 22 juni 2005 @ 14:39:
Je moet eerst de UBB-code parsen. Dan kun je met onderstaande RegExp alle niet-subdomein-url's omzetten:

/\b(?:www|http://www)\.([^\.]+\.\w{2,3}(?:\?[\w\d=&_-]+)?)\b/http://www.$1/ig

De RegExp voor subdomeinen post ik straks.
De UBB code is geparsed, maar voor het gemak heb ik die code hier weggelaten, omdat die goed werkt. Jouw regex werkt gedeeltelijk, dat wil zeggen: url's worden wel volledig gemaakt (dus de www.google.be wordt http://www.google.be), maar ze worden nog niet gehyperlinked (<a href=...). Als je dat wel zou toevoegen, zou je hetzelfde probleem krijgen als ik hierboven heb, omdat de regex ook al gehyperlinkte urls pakt.

Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
thanks, ben er al mee aan het stoeien, maar het lukt me nog niet om mijn regex werked te krijgen. Lijkt wel of de lookbehind en lookahead niet werken...

Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
ok, ik ben d'r uit... Een beetje van mezelf, en een beetje van The Regex Coach... Erg handig om ff snel regex te testen, en om te zien hoe ie het doorloopt.

Mocht iemand het nodig hebben:
code:
1
$message = preg_replace('`(?<!<a href=")((http)+(s)?:(//)|(www\.))((\w|\.|\-|\_)+)(/)?(\s|$|<)`i', '<a href="http\\3://\\5\\6\\8" target="_blank">\\5\\6</a>\9', $message);


Getest met allerhande URL's, op allerlei plaatsen in zinnen, aan het begin, halverwege en aan het eind. Lijkt goed te werken :)

Acties:
  • 0 Henk 'm!

  • imp4ct
  • Registratie: November 2003
  • Laatst online: 06-09 22:19
'k Heb een andere versie. Als je de search functie even had gebruikt had je hem zeker gevonden. Post was nog niet zo lang van't forum verdwenen. Deze werkt enkel als je op UBB [url] taggs gebruikt.
Wel rekening houdend, mijn UBB code wordt door een ander script lowercase gebracht en al mijn [url] taggs worden omgezet naar deze weergave.

code:
1
[url=delink]detekst-of-delink[/url]


PHP:
1
$htmlpost = preg_replace("#\\[url(=([^\\[\]]*))?\]([^\\[\]]*)\\[/(url)\]#e", "'<a href=\"' . ('\\2' == '' ? '\\3' : '\\2') . '\" target=\"_blank\">\\3</a>'", $htmlpost);


PS : is er misschien interesse naar een heus regex-topic, waar iedereen zijn regex uitvindingen kan posten ?

[ Voor 102% gewijzigd door imp4ct op 22-06-2005 20:30 ]

Bedrijf : Webtrix

Foto materiaal:
Nikon D7100 | Nikor AF-S DX 18-105mm | Nikor AF-S 50mm | Nikon SB600


Acties:
  • 0 Henk 'm!

  • Schonhose
  • Registratie: April 2000
  • Laatst online: 17-09 20:01

Schonhose

Retro Icoon

I_M_P_A_C_T schreef op woensdag 22 juni 2005 @ 20:22:
is er misschien interesse naar een heus regex-topic, waar iedereen zijn regex uitvindingen kan posten ?
Gewoon een soort regex database bedoel je? Omschrijving, regex statement, input en output?

Is misschien wel handig als mensen wat zoeken. Ik denk dat het alleen succes heeft wanneer je de regex duidelijk uitlegt zodat mensen het ook kunnen snappen (i.p.v. klakkeloos kopieren).

offtopic:
Ik zal eens even wat modjes aan hun jasje trekken ;)

[ Voor 7% gewijzigd door Schonhose op 23-06-2005 08:00 ]

"The thing under my bed waiting to grab my ankle isn't real. I know that, and I also know that if I'm careful to keep my foot under the covers, it will never be able to grab my ankle." - Stephen King
Quinta: 3 januari 2005


Acties:
  • 0 Henk 'm!

  • compufreak88
  • Registratie: November 2001
  • Laatst online: 02-05 17:51
Zoiets is er eigenlijk ook al: www.regexplib.com. Daar staan al heel wat regexpen opgeslagen. Er is ook een testpagina.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

Je kan ook andersom checken of er voor de mogelijke URL wel whitespace staat:
code:
1
(?<=\s|^)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Ik zou gewoon "pear install HTML_BBCodeParser" doen, en dan die gaan gebruiken :)

Zie ook http://pear.php.net/package/HTML_BBCodeParser/ en http://nautadereede.nl/parser/parser.php

Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
I_M_P_A_C_T schreef op woensdag 22 juni 2005 @ 20:22:
'k Heb een andere versie. Als je de search functie even had gebruikt had je hem zeker gevonden. Post was nog niet zo lang van't forum verdwenen. Deze werkt enkel als je op UBB [url] taggs gebruikt.
Wel rekening houdend, mijn UBB code wordt door een ander script lowercase gebracht en al mijn [url] taggs worden omgezet naar deze weergave.

code:
1
[url=delink]detekst-of-delink[/url]


PHP:
1
$htmlpost = preg_replace("#\\[url(=([^\\[\]]*))?\]([^\\[\]]*)\\[/(url)\]#e", "'<a href=\"' . ('\\2' == '' ? '\\3' : '\\2') . '\" target=\"_blank\">\\3</a>'", $htmlpost);


PS : is er misschien interesse naar een heus regex-topic, waar iedereen zijn regex uitvindingen kan posten ?
Reuze leuk dat jij een andere versie hebt. Ik heb de search wel degelijk gebruikt. Als jij even mijn startpost had doorgelezen, had je gezien dat ik de [ url ] tags al laat parsen, maar dat ik OOK urls ZONDER die bbcode tag wil laten omzetten!

Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
chris schreef op donderdag 23 juni 2005 @ 13:23:
Ik zou gewoon "pear install HTML_BBCodeParser" doen, en dan die gaan gebruiken :)

Zie ook http://pear.php.net/package/HTML_BBCodeParser/ en http://nautadereede.nl/parser/parser.php
das opzich een mooi pakketje... alleen de lijst met bugs is vrij lang. onder andere urls die zijn neergezet als "www.blaat.com" pakt ie niet goed (wordt geen http:// voor gezet in de href)

Acties:
  • 0 Henk 'm!

Verwijderd

Wat ik me altijd afvraag is waarom zulke problemen met een preg_replace worden geprobeerd om op te lossen. Wat veel minder foutgevoelig is, is om met preg_split eerst een string in tokens op te delen. Dan heb je één regular expression nodig die alle tokens beschrijft. Vervolgens heb je voor elke token een manier nodig om het te kunnen herkennen, bijvoorbeeld nog een regular expression.

Maar doordat je alle tokens stuk voor stuk afloopt, kun je meteen een stack bijhouden, en is het een fluitje van een cent om dit soort problemen op te lossen. Je zult dan alleen maar hoeven zorgen dat alle UBB tags en URL's als een token gezien worden.

Acties:
  • 0 Henk 'm!

  • MaTriCX
  • Registratie: Augustus 2002
  • Laatst online: 18-07-2024
Verwijderd schreef op zondag 26 juni 2005 @ 13:37:
Wat ik me altijd afvraag is waarom zulke problemen met een preg_replace worden geprobeerd om op te lossen. Wat veel minder foutgevoelig is, is om met preg_split eerst een string in tokens op te delen. Dan heb je één regular expression nodig die alle tokens beschrijft. Vervolgens heb je voor elke token een manier nodig om het te kunnen herkennen, bijvoorbeeld nog een regular expression.

Maar doordat je alle tokens stuk voor stuk afloopt, kun je meteen een stack bijhouden, en is het een fluitje van een cent om dit soort problemen op te lossen. Je zult dan alleen maar hoeven zorgen dat alle UBB tags en URL's als een token gezien worden.
Een voorbeeld van een UBBParser waarbij dit principe wordt toegepast is de EamUBBParser . Deze parser is vrij uitgebreid en begrijpelijk toegelicht.

Hiermee is het probleem van het omzetten van een normale URL nog steeds aan de orde.

Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
Kauwgomballen schreef op woensdag 22 juni 2005 @ 20:03:
ok, ik ben d'r uit... Een beetje van mezelf, en een beetje van The Regex Coach... Erg handig om ff snel regex te testen, en om te zien hoe ie het doorloopt.

Mocht iemand het nodig hebben:
code:
1
$message = preg_replace('`(?<!<a href=")((http)+(s)?:(//)|(www\.))((\w|\.|\-|\_)+)(/)?(\s|$|<)`i', '<a href="http\\3://\\5\\6\\8" target="_blank">\\5\\6</a>\9', $message);


Getest met allerhande URL's, op allerlei plaatsen in zinnen, aan het begin, halverwege en aan het eind. Lijkt goed te werken :)
Ok, dit is toch niet helemaal de goede oplossing... Hij maakt alleen URL's clickable als ze een domeinnaam bevatten, als ze langer zijn dan alleen een domeinnaam (bijvoorbeeld www.site.nl/index.php?id=8) dan werkt ie niet goed. Heb nu bovenstaande uitgebreid naar dit:
code:
1
$message = preg_replace('`(?<!<a href=")((http)+(s)?:(//)|(www\.))((\w|\.\w|\-|\_|\/|\?\w|\=\w|\&amp;\w)+)`i', '<a href="http\\3://\\5\\6\\8" target="_blank">\\5\\6\\8</a>\9', $message);

Deze werkt opzich, maar heeft als probleem dat ie reeds omgezette URL's nóg een keer gaat omzetten, terwijl dat volgens mij niet zou moeten, omdat die exclude ervoor staat? Ben er al weer uren mee aan het stoeien, maar kom er toch weer niet uit... Iemand die 'm wel weet?

Acties:
  • 0 Henk 'm!

  • imp4ct
  • Registratie: November 2003
  • Laatst online: 06-09 22:19
Persoonlijk zou'k het gewoon in 2 stappen oplossen, 1 ding dat kijk als er UBB code staat en 1 als je gewoon met een getypte link werkt, want alles in 1 keer doen, 'k weet het niet, het zal waarschijnlijk wel mogelijk zijn, maar dan maak je het zo ingewikkeld en moet je met zoooveel uitzonderingen rekening gaan houden.

'k Weet dat mijn eerder geposte UBB convertor rock-solid zou moeten zijn, nu zoek ik zelf nog een gewone link convertor die ook volledig werkt op alles, 'k zal die van jou ook eens bekijken.

Normaal als je de search functie van't forum even gebruikt vind je wel http:// convertors hoor die volledig werken.

[ Voor 13% gewijzigd door imp4ct op 22-07-2005 22:46 ]

Bedrijf : Webtrix

Foto materiaal:
Nikon D7100 | Nikor AF-S DX 18-105mm | Nikor AF-S 50mm | Nikon SB600


Acties:
  • 0 Henk 'm!

  • SuperRembo
  • Registratie: Juni 2000
  • Laatst online: 20-08 14:36
Ik gebruik zelf deze regexps. Eerst worden de losse urls voorzien van een url tag, daarna worden alle url tags omgezet naar html.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// http://foo.net => [url=http://foo.net]http://foo.net[/url]
// not urls after = or ="
'#(?<!=)(?<!=")(https?://\S+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=\1]\1[/url]',

// www.foo.net => [url=www.foo.net]http://www.foo.net[/url]
'#(?<=^|\s)(www\.[a-z0-9\.\-_%?&=;\#/]+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=http://\1]\1[/url]',

// [url=http://foo.net]Foo[/url] => <a href="http://foo.net">Foo</a>
'#(?<!\\\\)\[url=(https?://\S*?)\](.*?)\\[/url\]#i'
    => '<a class="link" href="\1">\2</a>',

// [url=foo.net]Foo[/url] => <a href="http://foo.net">Foo</a>
'#(?<!\\\\)\[url=(\S+?)\](.+?)\\[/url\]#i'      
    => '<a class="link" href="http://\1">\2</a>',


Ik heb er een keer een xmlhttp scriptje omheen gebouwd, zo kan je makkelijk testen en zie je snel wanneer het parsen verkeerd gaat. (Niet aan te raden om echt te gebruiken in een postsysteem, op elke keypress gaat het hele bericht heen en weer naar de server :P)

[ Voor 19% gewijzigd door SuperRembo op 23-07-2005 12:24 ]

| Toen / Nu


Acties:
  • 0 Henk 'm!

  • imp4ct
  • Registratie: November 2003
  • Laatst online: 06-09 22:19
SuperRembo schreef op zaterdag 23 juli 2005 @ 11:05:
Ik gebruik zelf deze regexps. Eerst worden de losse urls voorzien van een url tag, daarna worden alle url tags omgezet naar html.

PHP:
1
2
3
4
// www.foo.net => [url=www.foo.net]http://www.foo.net[/url]
////'#(?<!\\[url=)(?<!http://)(?<=\s|^)(www\.\S+?)(?=[.,?:;()<>]*(\s|$))#i'
'#(?<=^|\s)(www\.[a-z0-9\.\-_%?&=;\#/]+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=http://\1]\1[/url]',
moet het bij die tweede niet dit zijn ?

PHP:
1
2
3
4
// www.foo.net => [url=http://www.foo.net]www.foo.net[/url]
////'#(?<!\\[url=)(?<!http://)(?<=\s|^)(www\.\S+?)(?=[.,?:;()<>]*(\s|$))#i'
'#(?<=^|\s)(www\.[a-z0-9\.\-_%?&=;\#/]+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=http://\1]\1[/url]',

Bedrijf : Webtrix

Foto materiaal:
Nikon D7100 | Nikor AF-S DX 18-105mm | Nikor AF-S 50mm | Nikon SB600


Acties:
  • 0 Henk 'm!

  • SuperRembo
  • Registratie: Juni 2000
  • Laatst online: 20-08 14:36
En het verschil is? :?

(die 2e regel commectaar is een oude regexp die ik was vergeten weg te halen)

| Toen / Nu


Acties:
  • 0 Henk 'm!

  • imp4ct
  • Registratie: November 2003
  • Laatst online: 06-09 22:19
Wel

PHP:
1
2
3
4
5
6
7
8
9
10
11
jou versie :

<?
// www.foo.net => [url=www.foo.net]http://www.foo.net[/url]
?>

mijn versie :

<?
// www.foo.net => [url=http://www.foo.net]www.foo.net[/url]
?>


Je had gewoon die "http://" even moeten omdraaien mits je dit ook zo doet in je regex :)

PHP:
1
2
3
4
<?
'#(?<=^|\s)(www\.[a-z0-9\.\-_%?&=;\#/]+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=http://\1]\1[/url]',
?>

Bedrijf : Webtrix

Foto materiaal:
Nikon D7100 | Nikor AF-S DX 18-105mm | Nikor AF-S 50mm | Nikon SB600


Acties:
  • 0 Henk 'm!

  • SuperRembo
  • Registratie: Juni 2000
  • Laatst online: 20-08 14:36
Aha. alleen 't commentaar was fout. De regexp was goed. Ik had alleen de regexps naast elkaar gelegd en zag geen verschil.

| Toen / Nu


Acties:
  • 0 Henk 'm!

  • imp4ct
  • Registratie: November 2003
  • Laatst online: 06-09 22:19
Héhé, neen neen, je regex was perfect in orde, 'k ga hem zelfs gebruiken :), dus thx !! :)

Bedrijf : Webtrix

Foto materiaal:
Nikon D7100 | Nikor AF-S DX 18-105mm | Nikor AF-S 50mm | Nikon SB600


Acties:
  • 0 Henk 'm!

  • kauwgomballen
  • Registratie: Oktober 2001
  • Laatst online: 23-06 19:54
SuperRembo schreef op zaterdag 23 juli 2005 @ 11:05:
Ik gebruik zelf deze regexps. Eerst worden de losse urls voorzien van een url tag, daarna worden alle url tags omgezet naar html.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// http://foo.net => [url=http://foo.net]http://foo.net[/url]
// not urls after = or ="
'#(?<!=)(?<!=")(https?://\S+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=\1]\1[/url]',

// www.foo.net => [url=www.foo.net]http://www.foo.net[/url]
'#(?<=^|\s)(www\.[a-z0-9\.\-_%?&=;\#/]+?)(?=[.,!?:()<>]*(\s|$))#i'
    => '[url=http://\1]\1[/url]',

// [url=http://foo.net]Foo[/url] => <a href="http://foo.net">Foo</a>
'#(?<!\\\\)\[url=(https?://\S*?)\](.*?)\\[/url\]#i'
    => '<a class="link" href="\1">\2</a>',

// [url=foo.net]Foo[/url] => <a href="http://foo.net">Foo</a>
'#(?<!\\\\)\[url=(\S+?)\](.+?)\\[/url\]#i'      
    => '<a class="link" href="http://\1">\2</a>',


Ik heb er een keer een xmlhttp scriptje omheen gebouwd, zo kan je makkelijk testen en zie je snel wanneer het parsen verkeerd gaat. (Niet aan te raden om echt te gebruiken in een postsysteem, op elke keypress gaat het hele bericht heen en weer naar de server :P)
_/-\o_
Ik dank u op mijn blote knietjes! Aan deze oplossing had ik helemaal nog niet gedacht! Dit werkt perfect, beter dan mijn oplossing proberen te verbeteren.
Pagina: 1