Avatar billede venchil Nybegynder
27. april 2010 - 21:33 Der er 13 kommentarer og
1 løsning

regex troubles...

Hej Eksperter!

Jeg sidder med et stykke PHP-kode, der skal kunne følgende:

Sætte "<span>" før hvert ord og "&nbsp;</span>" efter hvert ord, men ignorere links. Jeg har f.eks. følgende HTML-streng:

Dette er en test-streng <a href="#">Link</a>

Det skulle gerne laves om til:

<span>Dette&nbsp;</span><span>er&nbsp;</span><span>en&nbsp;</span><span>test-streng&nbsp;</span><a href="#">Link</a>

Umiddelbart ser det dumt ud med alle de spans, men de tjener et formål. Er der en måde at gøre ovenstående med regex / PHP ?

På forhånd tak! (150 point udloves)
Avatar billede arne_v Ekspert
27. april 2010 - 22:38 #1
Forslag:

function spaning ($s) {
    preg_match_all('#(.*?)(<a .*?</a>)(.*?)#is', $s, $parts);
    $res = '';
    for($i = 0; $i < count($parts[0]); $i++) {
        $res .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[1][$i]);
        $res .= $parts[2][$i];
        $res .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[3][$i]);
    }
    return $res;
}
Avatar billede venchil Nybegynder
29. april 2010 - 12:34 #2
Der er stadig mellemrum mellem mine spans. Er der en smart måde at fjerne dem på, eller er det bare en str_replace(' ', '', $res); ?
Avatar billede arne_v Ekspert
29. april 2010 - 18:08 #3
Noget i den stil.

F.eks.:

function spaning ($s) {
    preg_match_all('#(.*?)(<a .*?</a>)(.*?)#is', $s, $parts);
    $res = '';
    for($i = 0; $i < count($parts[0]); $i++) {
        $res .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[1][$i]);
        $res .= $parts[2][$i];
        $res .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[3][$i]);
    }
    return str_replace('</span> <span>', '</span><span>', $res);
}
Avatar billede venchil Nybegynder
30. april 2010 - 00:31 #4
Okay, det har jeg tilføjet nu, men der er tilsyneladende et lille problem. Efter et link i starten bliver resten af teksten cuttet af af preg_match_all

Min kode:

$test = 'Dette <a href="http://google.com/">link</a> er her, men resten virker ikke';
preg_match_all('#(.*?)(<a .*?</a>)(.*?)#is', $test, $parts);
$result = '';
for ($i=0; $i < count($parts[0]); $i++) {
    $result .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[1][$i]);
    $result .= $parts[2][$i];
    $result .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[3][$i]);
}
$result = str_replace('</span> <span>', '</span><span>', $result);
$result = str_replace('</span> <a', '</span><a', $result);

echo $result;

Hvad er der galt her? :S
Avatar billede arne_v Ekspert
30. april 2010 - 02:37 #5
Prøv:

preg_match_all('#(.*?)(<a .*?</a>)((.*(?=<a))|(.*$))#is', $test, $parts);
Avatar billede arne_v Ekspert
30. april 2010 - 03:25 #6
Prøv:

preg_match_all('#(.*?)(<a .*?</a>)((.*(?=<a))|(.*$))#is', $test, $parts);
Avatar billede venchil Nybegynder
30. april 2010 - 23:14 #7
Det fixede det, men der er endnu et lille sidste problem: kommaer bliver tilsyneladende smidt ud af mine <span>-elementer. På dette tidspunkt er jeg helt stået af (er absolut ikke regex-mester) og kan simpelthen ikke se hvorfor de gør det.



Kode:
$test = 'Dette <a href="http://google.com/">link</a> er her, men resten virker ikke';
preg_match_all('#(.*?)(<a .*?</a>)((.*(?=<a))|(.*$))#is', $test, $parts);
$result = '';
for ($i=0; $i < count($parts[0]); $i++) {
    $result .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[1][$i]);
    $result .= $parts[2][$i];
    $result .= preg_replace('#\b(\S+)\b#', '<span>$1&nbsp;</span>',$parts[3][$i]);
}
$result = str_replace('</span> <span>', '</span><span>', $result);
$result = str_replace('</span> <a', '</span><a', $result);

echo $result;



Output:
<span>Dette&nbsp;</span><a href="http://google.com/">link</a> <span>er&nbsp;</span><span>her&nbsp;</span>, <span>men&nbsp;</span><span>resten&nbsp;</span><span>virker&nbsp;</span><span>ikke&nbsp;</span>
Avatar billede arne_v Ekspert
01. maj 2010 - 04:29 #8
Komma er en del af word speerator \b.

Hvis komma skal opfattes som en del af ordet så prøv:

preg_match_all('#(.*?)(<a .*?</a>)((.*(?=<a))|(.*$))#is', ' ' . $test . ' ', $parts);
$result = '';
for ($i=0; $i < count($parts[0]); $i++) {
    $result .= preg_replace('#(?<=[ ])(\S+)(?=[ ])#', '<span>$1&nbsp;</span>',$parts[1][$i]);
    $result .= $parts[2][$i];
    $result .= preg_replace('#(?<=[ ])(\S+)(?=[ ])#', '<span>$1&nbsp;</span>',$parts[3][$i]);
}
$result = substr($result, 1, strlen($result)-2);
$result = str_replace('</span> <span>', '</span><span>', $result);
$result = str_replace('</span> <a', '</span><a', $result);
Avatar billede venchil Nybegynder
02. juni 2010 - 21:43 #9
Jeg undskylder den sene respons, men det virker helt perfekt! Læg gerne et svar.
Avatar billede arne_v Ekspert
02. juni 2010 - 22:02 #10
svar
Avatar billede venchil Nybegynder
04. juni 2010 - 14:58 #11
Svar er accepteret, men der er én allersidste fejl jeg meget gerne ville have styr på: Hvis der er 2 links lige efter hinanden, sker der noget meget mærkeligt.

Kode:

<?php

$test = 'Tester <a href="http://google.com/">links</a> <a href="http://google.com/">links</a> lige her, lorem ipsum dolor <a href="http://google.com/">link</a> <a href="http://google.com/">link</a>';

preg_match_all('#(.*?)(<a .*?</a>)((.*(?=<a))|(.*$))#is', ' ' . $test . ' ', $parts);
$result = '';
for ($i=0; $i < count($parts[0]); $i++) {
    $result .= preg_replace('#(?<=[ ])(\S+)(?=[ ])#', '<span>$1&nbsp;</span>',$parts[1][$i]);
    $result .= $parts[2][$i];
    $result .= preg_replace('#(?<=[ ])(\S+)(?=[ ])#', '<span>$1&nbsp;</span>',$parts[3][$i]);
}
$result = substr($result, 1, strlen($result)-2);
$result = str_replace('</span> <span>', '</span><span>', $result);
$result = str_replace('</span> <a', '</span><a', $result);

echo $result;

?>


Output:
Tester [links] href="http://google.com/">links lige her, lorem ipsum dolor href="http://google.com/">link [link]


Hvor links med [] rundt om rent faktisk virker. Kan det have noget at gøre med mellemrummet mellem <a og href ?

Tusind tusind tak anyway
Avatar billede arne_v Ekspert
07. juni 2010 - 03:25 #12
svar er ikke accepteret

du skal sætte et flueben og klikke accepter
Avatar billede arne_v Ekspert
07. juni 2010 - 03:33 #13
preg_match_all('#(.*?)(<a .*?</a>)((.*(?=<a))|(.*$))#is', ' ' . $test . ' ', $parts);

->

preg_match_all('#(.*?)(<a .*?</a>)((.*?(?=<a))|(.*$))#is', ' ' . $test . ' ', $parts);
Avatar billede arne_v Ekspert
13. juni 2010 - 04:29 #14
Og et svar igen
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester