Avatar billede blackscorpion Nybegynder
10. maj 2008 - 04:09 Der er 33 kommentarer og
1 løsning

Problemer med Regular Expression Match

Hej E.

Sidder og skal have bygget 2 scripts sammen, og det volder mig store problemer.

Script 1:

Hiver data ud fra databasen, og kører dem igennem en while med tilknyttet "extract($content);" på den, hvor vi får $text ud.

koden ser sådan her ud:

while($content = mysql_fetch_array($result)) {
extract($content);

$code = highlight_string($text, true);
$code = explode("<br />", $code);

$i = "1";
foreach ($code as $line => $syntax) {

  if($i < 10) {
  $i = "0".$i;
  }

  echo "<font color='black'>".$i."</font> ".$syntax."<br>";
  $i++;
}

Det er til syntax highlight, og det virker fint fint.

Script 2:

Det er til at køre koden igennem og tjekke for evt. special kodening. (lige som med BBcode)

$html2 indeholder en test string, med forskellige ting i, bla: [b[/b] og [a href=howdy.html]click me[/a]

preg_match_all("/(\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])/i", $html2, $matches, PREG_SET_ORDER);

foreach ($matches as $val) {
    echo "matched: " . htmlentities($val[0]) . "<br>\n";
    echo "part 1: " . htmlentities($val[1]) . "<br>\n";
    echo "part 2: " . htmlentities($val[3]) . "<br>\n";
    echo "part 3: " . htmlentities($val[4]) . "<br>\n\n";
}

Nu prøver jeg så at få dem sat sammen, sådan at den kører scriptet igennem først, for at finde special kodning, og i $text i databasen, har jeg noget test, og så nogle tags der hedder [phpcode][/phpcode] med kode imellem.

Målet er så, at den kører igennem for special tags, udskifter hvor nødvendigt, og sætter koden imellem [phpcode][/phpcode] i en highlight_string, sådan at den får syntax highlight på. :)

Resultatet jeg sidder ved nu ser således ud:

while($content = mysql_fetch_array($result)) {
extract($content);

preg_match_all("/(\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])/i", $text, $matches, PREG_SET_ORDER);

foreach ($matches as $val) {
    echo "matched: " . htmlentities($val[0]) . "<br>\n";
    echo "part 1: " . htmlentities($val[1]) . "<br>\n";
    echo "part 2: " . htmlentities($val[3]) . "<br>\n";
    echo "part 3: " . htmlentities($val[4]) . "<br>\n\n"; 
}

/*
$code = highlight_string($text, true);
$code = explode("<br />", $code);

$i = "1";
foreach ($code as $line => $syntax) {

  if($i < 10) {
  $i = "0".$i;
  }

  echo "<font color='black'>".$i."</font> ".$syntax."<br>";
  $i++;
}
*/
}

Den får jeg blank skærm på.
Har prøvet at udskifte preg_match_all med preg_match, men det giver en fejl.

Nogle der har nogle bud på hva jeg gør galt, og hvordan jeg når mit mål ? :)

ps. skal på job om lidt, og er først hjemme omkring 19 tiden i aften, sådan ca.

- BlackScorpion.
Avatar billede tmi Nybegynder
10. maj 2008 - 18:47 #1
Det kan du ikke :-P
Som udgangspunkt er folk mongoler.. De laver fx nice[/i] <- doh!
Men du kan da prøve.. Jeg vil gøre sådan her:

<?
   
    function bbcode($starttag, $content, $endtag) {
        // hvis der er fejl i tagsne, fx starter med [b] og slutter med [i]:
        if ($starttag != $endtag) return $content;
       
        switch ($starttag) {
            case 'b': return "<b>$content</b>";
            case 'i': return "<i>$content</i>";
            case 'u': return "<u>$content</u>";
            case 'phpcode': return highlight_string($content, true);
        }
    }
    function bbcode2html($text) {
        return nl2br(preg_replace("#\[([a-z]+)](.+)\[/([a-z]+)]#Ues", "bbcode('\\1','\\2','\\3')", $text));
    }
   
    $text = '
her er noget [b]php kode
:
[phpcode]
<?
    function max($a, $b) {
        return $a > $b ? $a : $b;
    }
?>
[/phpcode]';
   
    echo bbcode2html($text);
   
   
?>
Avatar billede blackscorpion Nybegynder
10. maj 2008 - 18:52 #2
sorry m8, men du tager udgangspunkt i at den kun skal glo efter BBkodening, og overser pointen i spørgsmålet. :P

Se væk fra bb kodeningen... skal bare have de 2 scripts til at spille sammen. ;)
Avatar billede tmi Nybegynder
11. maj 2008 - 14:32 #3
Jeg tror bare du skal tilføjse modifiereren "s" i dit regulære udtryk.. Hvis det altså er fordi den ikke matcher noget. For der ser ikke ud til at være noget galt med det.
Avatar billede tmi Nybegynder
11. maj 2008 - 14:33 #4
altså

preg_match_all("/(\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])/is", $text, $matches, PREG_SET_ORDER);

så matcher . også linjeskift
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 18:49 #5
nu er mit problem så bare at jeg ikke kan smide tekst rundt om, uden at den sætter koden øverst. :S
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 18:57 #6
nu har jeg fået den til følgende:

først på siden, spytter den koden ud.

så skriver den følgende:

-----------------------
Dette er så et lille stykke kode jeg har brygget sammen over natten, for lige at teste databasen, og så hvordan den håndterer phpkode, samt hvordan jeg får det til at se pænt ud på siden. :)

1

Fortæl mig hvad i syntes. :) - Admin
----------------------------------------------

hvor 1 skulle være koden :S

min kode ser sådan her ud indtil videre:

preg_match_all("/(\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])/is", $text, $matches, PREG_SET_ORDER);

foreach ($matches as $val) {
    //echo "part 2: " . highlight_string($val[3]) . "<br>\n";
   
    if(htmlentities($val[1]) == "" AND htmlentities($val[4]) == "") {
    $html2 = str_replace("","<b>", $html2);
    $html2 = str_replace("
","</b>", $html2);
    }
   
    if(htmlentities($val[4]) == "[/a]") {
   
    $part1 = str_replace("[a", "<a", htmlentities($val[1]));
    $part1 = str_replace("]", ">", $part1);
    $part3 = str_replace("[/a]","</a>", htmlentities($val[4]));
   
    $complete_replacement = $part1.htmlentities($val[3]).$part3;
   
    $text = str_replace(htmlentities($val[0]), $complete_replacement, $text);
    }
   
    if(htmlentities($val[1]) == "[phpcode]" AND htmlentities($val[4]) == "[/phpcode]") {
    $text = str_replace("[phpcode]","<div style='border:1px solid black; width: 575px'>", $text);
    // $text = str_replace("&lt", "<", $text);  htmlentities($val[3]) = highlight_string(htmlentities($val[3]));
   
    $text = str_replace($val[3], highlight_string($val[3]), $text);
   
    $text = str_replace("[/phpcode]","</div>", $text);
    }
   
}

echo "<br>".$text;
?>
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 19:03 #7
hmm lader ikke til jeg kan få lov at lave en str_replace på noget af det kode som highlight_string generere. :(
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 19:09 #8
*banker hovedet i bordet*

Elsker når jeg glemmer noget. ;)

$text = str_replace($val[3], highlight_string($val[3]), $text); = $text = str_replace($val[3], highlight_string($val[3], true), $text);

så virker det. ;)
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 19:10 #9
Men tmi, smid et svar.. dit "s" var det manglende link, jeg ikke selv kunne overkomme. ;)
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 19:15 #10
Hmm lagde lige mærke til at den ikke virker hvis jeg laver følgende:

tekst

phpcode

tekst

phpcode

det virker kun hvis der er phpcode 1 gang. :S
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 19:28 #11
hmm det har kan jeg ikke helt blive klog på... virker som om at ved at rykke str_replace("[phpcode].... og str_replace("[/phpcode .... uden for foreach løkken, så virker det. :S
Avatar billede tmi Nybegynder
11. maj 2008 - 19:53 #12
Jf. min første post, skal du bruge preg_replace med e modifier (evt. preg_replace_callback).. Den gør det du ønsker, men ordentligt, det der er åndsvagt
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 20:02 #13
Der tabte du mig lige... hvilke ændringer vil du have hvor, i denne kode ?

  preg_match_all("/(\[([\w]+)[^\]]*\])(.*)(\[\/\\2\])/is", $text, $matches, PREG_SET_ORDER);

foreach ($matches as $val) {
    if(htmlentities($val[4]) == "[/a]") {
   
    $part1 = str_replace("[a", "<a", htmlentities($val[1]));
    $part1 = str_replace("]", ">", $part1);
    $part3 = str_replace("[/a]","</a>", htmlentities($val[4]));
   
    $complete_replacement = $part1.htmlentities($val[3]).$part3;
   
    $text = str_replace(htmlentities($val[0]), $complete_replacement, $text);
    }
   
    if(htmlentities($val[1]) == "[phpcode]" AND htmlentities($val[4]) == "[/phpcode]") {
    //$text = str_replace("[phpcode]","<div style='border:1px solid black; width: 575px; padding: 5px; font-size: 12px'>", $text);   
    $text = str_replace($val[3], highlight_string($val[3], true), $text);   
    $text = str_replace("<br /><span style=\"color: #0000BB\">&lt;?php", "<span style=\"color: #0000BB\">&lt;?php", $text);
    //$text = str_replace("[/phpcode]","</div>", $text);
    }   
}

    $text = str_replace("","<b>", $text);
    $text = str_replace("
","</b>", $text);
$text = str_replace("[/phpcode]","</div>", $text);
$text = str_replace("[phpcode]","<div style='border:1px solid black; width: 575px; padding: 5px; font-size: 12px'>", $text);   
echo "<br>".$text;
?>
Avatar billede tmi Nybegynder
11. maj 2008 - 20:34 #14
Din kode vil gøre at hvis jeg poster:

Se min kode.. Jeg elsker [phpcode]kode[/phpcode]

Så bliver "kode" highlighted begge steder. Det ville det ikke gøre i mit eksempel
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 20:52 #15
hmm... det gør den ikke på min... har lige prøvet. :S
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 20:58 #16
http://www.alabit.dk/test/testme.php

test det her, og se om du kan finde noget den dobbelt highlighter som den ikke skal. :)
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 21:06 #17
Efter test i ie explorer kan jeg godt se hvad du mener... :S

sad før og spekulerede på hvordan jeg kunne lave så den kun ændre den del af koden som den SKAL ændre.
Avatar billede tmi Nybegynder
11. maj 2008 - 21:16 #18
Det har jeg jo fortalt dig 4 gange nu, hvordan du gør..

function bbcode($starttag, $content, $endtag) {
        // hvis der er fejl i tagsne, fx starter med [b] og slutter med [i]:
        if ($starttag != $endtag) return $content;
     
        switch ($starttag) {
            case 'b': return "<b>$content</b>";
            case 'i': return "<i>$content</i>";
            case 'u': return "<u>$content</u>";
            case 'phpcode': return highlight_string($content, true);
        }
    }
    function bbcode2html($text) {
        return nl2br(preg_replace("#\[([a-z]+)](.+)\[/([a-z]+)]#Ues", "bbcode('\\1','\\2','\\3')", $text));
    }


    $text = bbcode2html($text);
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 21:16 #19
har nu testet dit eksempel fra din første post... den spytter følgende ud:

<?php



require("config/config.inc.php\");

require(\"config/functions.inc.php\");



$uri = \"index.php\";

i databasen står det sådan her:

<?php

require("config/config.inc.php");
require("config/functions.inc.php");

$uri = "index.php";
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 21:33 #20
nl2br skal selvfølgelig væk.. men har stadig ikke løst den del med \" foran.. og det er en del af den preg_replace du har.
Avatar billede tmi Nybegynder
11. maj 2008 - 21:50 #21
function bbcode($starttag, $content) {
       
        switch ($starttag) {
            case 'b':
                $content = "<b>$content</b>";
                break;
            case 'i':
                $content = "<i>$content</i>";
                break;
            case 'u':
                $content = "<u>$content</u>";
                break;
            case 'phpcode':
                $content = highlight_string($content, true);
                break;
        }
       
        return stripslashes($content);
    }
    function bbcode2html($text) {
        return preg_replace("#\[([a-z]+)](.+)\[/\\1]#Ues", "bbcode('\\1','\\2')", $text);
    }
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 21:52 #22
Sad og læstepå php net, efter en eventuel løsning... fandt dette:

People using the /e modifier with preg_replace should be aware of the following weird behaviour. It is not a bug per se, but can cause bugs if you don't know it's there.

The example in the docs for /e suffers from this mistake in fact.

With /e, the replacement string is a PHP expression. So when you use a backreference in the replacement expression, you need to put the backreference inside quotes, or otherwise it would be interpreted as PHP code. Like the example from the manual for preg_replace:

preg_replace("/(<\/?)(\w+)([^>]*>)/e",
            "'\\1'.strtoupper('\\2').'\\3'",
            $html_body);

To make this easier, the data in a backreference with /e is run through addslashes() before being inserted in your replacement expression. So if you have the string

He said: "You're here"

It would become:

He said: \"You\'re here\"

...and be inserted into the expression.
However, if you put this inside a set of single quotes, PHP will not strip away all the slashes correctly! Try this:

print ' He said: \"You\'re here\" ';
Output: He said: \"You're here\"

This is because the sequence \" inside single quotes is not recognized as anything special, and it is output literally.

Using double-quotes to surround the string/backreference will not help either, because inside double-quotes, the sequence \' is not recognized and also output literally. And in fact, if you have any dollar signs in your data, they would be interpreted as PHP variables. So double-quotes are not an option.

The 'solution' is to manually fix it in your expression. It is easiest to use a separate processing function, and do the replacing there (i.e. use "my_processing_function('\\1')" or something similar as replacement expression, and do the fixing in that function).

If you surrounded your backreference by single-quotes, the double-quotes are corrupt:
$text = str_replace('\"', '"', $text);

People using preg_replace with /e should at least be aware of this.

I'm not sure how it would be best fixed in preg_replace. Because double-quotes are a really bad idea anyway (due to the variable expansion), I would suggest that preg_replace's auto-escaping is modified to suit the placement of backreferences inside single-quotes (which seemed to be the intention from the start, but was incorrectly applied).

Så i bund og grund, er det det der e du har i #Ues der smider \ ind foran ". :S
Avatar billede blackscorpion Nybegynder
11. maj 2008 - 21:56 #23
resultatet på din sidste kode fjerner \ foran.. men som på den første, forbliver koden rød. :(
Avatar billede blackscorpion Nybegynder
12. maj 2008 - 01:11 #24
Fandt en anden løsning.

PEAR - Text_Highlighter 0.7.1.

Koden ser ud som følgende:

  require_once ("Text\Highlighter.php");
  $highlighter =& Text_Highlighter::factory('php');
  echo '<link rel="stylesheet" href="hilight.css" />';
  $text = $highlighter->highlight($text);
  $text = str_replace("  ", "&nbsp;&nbsp;", $text);
  $text = str_replace(" &nbsp; ", "&nbsp;&nbsp;", $text);
  $text = str_replace("[phpcode]", "<div style='border: 1px solid gray; width: 575px; padding: 10px; font-size: 12px'>", $text);
  $text = str_replace("[/phpcode]", "</div>", $text);
  echo $text;

Virker uden nogle hiks. :)
Avatar billede blackscorpion Nybegynder
12. maj 2008 - 01:11 #25
Du får point for din tid. ;)
Avatar billede tmi Nybegynder
12. maj 2008 - 10:11 #26
Brug preg_replace_callback så.. Det er det samme som /e, men der skal du ikke escape noget. Der er argumentet til funktionen arrayet med backreferencerne i
Avatar billede blackscorpion Nybegynder
12. maj 2008 - 18:26 #27
Fandt lige ud af at mit webhotel ikke har pear installeret, så sidder lige og roder med hvad du lige skrev.. og kan ikke helt få det til at virke. :S
Avatar billede tmi Nybegynder
13. maj 2008 - 22:29 #28
$text = "min testkode: [phpcode]<? echo "test"; ?>[/phpcode]

echo bbcode2html($text);

Virker det ikke? Hvis du har de to funktioner jeg skrev sidst?
Avatar billede blackscorpion Nybegynder
14. maj 2008 - 16:10 #29
Det er preg_replace_callback jeg har problemer med.. kan ikke få den til at acceptere bbcode('\\1', '\\2') den skriver at nummer 2 skal være et gyldigt argument.

Min kode ser sådan her ud:

function bbcode($starttag, $content) {
     
        switch ($starttag) {
            case 'b':
                $content = "<b>$content</b>";
                break;
            case 'i':
                $content = "<i>$content</i>";
                break;
            case 'u':
                $content = "<u>$content</u>";
                break;
            case 'phpcode':
                $content = highlight_string($content, true);
                break;
        }
     
        return stripslashes($content);
    }
    function bbcode2html($text) {
        return preg_replace_callback('#\[([a-z]+)](.+)\[/\\1]#Us', bbcode('\\1','\\2'), $text);
    }
   
    echo bbcode2html($text);
Avatar billede tmi Nybegynder
14. maj 2008 - 16:20 #30
Hvad skriver den helt præcist?
Prøv evt at tilføj modifier u, hvis du bruger utf8
Avatar billede blackscorpion Nybegynder
14. maj 2008 - 23:38 #31
den skriver følgende:

Warning: preg_replace_callback() [function.preg-replace-callback]: Requires argument 2, '2', to be a valid callback

modifier u.. der er jo U på den ?
Avatar billede blackscorpion Nybegynder
14. maj 2008 - 23:40 #32
databasen står til: Utf8_general_ci hvis det har nogen betydning.
Avatar billede tmi Nybegynder
15. maj 2008 - 01:09 #33
u = utf8, U = ungreedy

.. Har du overvejet at kigge i PHPs manual? Du bruger jo preg_replace_callback forkert.

Det kan vel ikke være så svært.. Brug den her funktion, den er nogenlunde ordentlig, så kan du vel selv regne ud hvordan du tilføjer bbkoder eller ændrer dem jeg har lavet i forvejen?:

<?


/**
* callback-functionen:
* argumenterne er array(0 => hele match, 1 => bbcode tag, 2 => rå bbcode atributter, 3 => bbkodens indhold)
**/
function bbcode($m) {
    // fjern mærkelige skråstreger:
    $content = stripslashes($m[3]);
   
    // put atributterne i et array:
    $attributes = array(); preg_match_all("#\b([a-z]+)\s*=\s*(\"|'|)(.+?)\\2\s#s", $m[2]." ", $attra);
    $length = count($attra[1]); for($i = 0; $i < $length; $i++) $attributes[$attra[1][$i]] = $attra[3][$i];
   
    // find ud af hvilket tag der er brugt:
    switch ($m[1]) {
        case 'a':
            $html = "<a";
            if ($attributes['color'])    $html .= " style='color:".$attributes['color']."'";
            if ($attributes['href'])    $html .= " href='".$attributes['href']."'";
            $content = $html.">".$content."</a>";
            break;
        case 'b':
            $content = "<b>$content</b>";
            break;
        case 'i':
            $content = "<i>$content</i>";
            break;
        case 's':
            $content = "<strike>$content</strike>";
            break;
        case 'u':
            $content = "<u>$content</u>";
            break;
        case 'phpcode':
            return highlight_string($content, true);
            // return fordi vi ikke vil have nestede tags
            break;
    }
   
    // check om der er nestede tags:
    return bbcode2html($content);
}
/**
* funktionen laver bbcode om til html
**/
function bbcode2html($text) {
    return preg_replace_callback("#\[([a-z]+)([^\]]*)](.+)\[/\\1]#Us", bbcode, $text);
}




$text = '
her er et [a href= http://www.mailbasen.dk/ color="red" ]link[/a], det er der ikke [s]her[/s].
her er [i]noget[/u] php kode:
[phpcode]
<?
    function max($a, $b) {
        return $a > $b ? $a : $b;
    }
?>
[/phpcode]';


echo nl2br(bbcode2html($text));


?>
Avatar billede blackscorpion Nybegynder
16. maj 2008 - 04:47 #34
tak...
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
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

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