/ Forside / Teknologi / Udvikling / PHP / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
PHP
#NavnPoint
rfh 3959
natmaden 3372
poul_from 3310
funbreak 2700
stone47 2230
Jin2k 1960
Angband 1743
Bjerner 1249
refi 1185
10  Interkril.. 1146
Regex, utilsigtet bivirkning med ekstra ba~
Fra : Jesper Brunholm


Dato : 09-08-06 09:57

Hejsa, jeg har en regex som hiver fodnoter med mere ud af databaselagret
indhold.

Eks. på indhold:
"... <p>Det er ikke rigtigt, at jeg har sendt "Politiken" noget Bidrag
til dets Drachmann-Nummer. Jeg har ikke engang været opfordret dertil,
og vilde heller ikke have gjort det, om det var sket. I vistnok 15 År
har jeg ikke set Drachmann, og i den Tid heller ikke skrifligt vekslet
Ord med ham.<slutnote><em>skriftligt vekslet Ord</em>: Det kendes kun
tre <a
href="http://www.henrikpontoppidan.dk/text/kilder/breve/drachmann/index.html">breve
fra HP</a> til Drachmann, det ældste er fra sommeren 1890, det næste fra
Berlin (22.12.1890), og det sidste er ikke 15, men 13 år gammelt
(29.12.1893). Men Pontoppidans formulering antyder at der tidligere har
været en også brevlig tættere kontakt mellem dem. Selv bevarede
Pontoppidan kun to breve fra Drachmann, det ene citerede han i <em>Arv
og Gæld???</em>, den andet ....</slutnote> Men jeg har jo i sin Tid
holdt meget af ham, og nu ved hans Fest..." [1]

PHP-kode:
function slutnote($notetekst){
global $slutnoter, $noteT_B; #slutnoter er et array hvori noterne
opbevares. $noteT_B er et array hvor notenumre konverteres til bogstaver
(fordi det er slutnoter som skal kunne skelnes fra fodnoter)
$pos=strtr(count($slutnoter), $noteT_B);
$slutnoter[$pos] = $notetekst;
$MyReturn = '<sup class="fodhenv"><a href="#fod'.$pos.'"
title="'.strip_tags($notetekst).'" id="note'.$pos.'">'.$pos.'</a></sup>';
return $MyReturn;
}// slutnote()

function udtraekNoter($tekst,$type='slutnote'){ # der kan både være
<fodnote> og <slutnote>'r
   $notepos = strpos($tekst, '<'.$type.'>');
   if(FALSE !== $notepos){
    $pattern='/<'.$type.'>(.*)<\/'.$type.'>/Ue';
    $tekst = preg_replace($pattern, "$type('\\1')", $tekst);
   }
return $tekst;
}// udtraekNoter()

- og endelig en funktion som printer fod- og slutnoterne ud nederst på
siden.

Det virker fint så længe der ikke er links i noteteksten. Det virker
også fint med fodnoter sat direkte i php-filer med <?php
fodnote('fodnotetekst her'); ?> med links i, så det er regex'en som
bugger links op og sætter ekstra anførselstegn-kode , de bliver fx. til:

"tre <a
href=\"http://www.henrikpontoppidan.dk/text/kilder/breve/drachmann/index.html\">breve
fra HP</a> til Drachman" - hvor altså \ er i overskud. Det kan ses i
funktion på
<http://www.henrikpontoppidan.dk/text/kilder/breve/borchsenius/1906_10_16.html#foda>

Kan nogen rette min regex, og gerne med forklaring?
Jeg er ikke ret hård til regex, og synes oprigtigt talt det er svært at
finde rundt i hvad der gør hvad. Det vil også sige at en god tutorial
til PHP (preg-)regex funktioner modtages med tak (og ja, jeg har læst
php-manualen igennem et par gange på det område ).

Mvh

Jesper Brunholm

[note 1: brevet er fra Henrik Pontoppidan til Otto Borchsenius og kan
ses på
<http://www.henrikpontoppidan.dk/text/kilder/breve/borchsenius/1906_10_16.html>
hvis nogen er interesserede i resten af indholdet].

 
 
Peter Brodersen (09-08-2006)
Kommentar
Fra : Peter Brodersen


Dato : 09-08-06 15:17

On Wed, 09 Aug 2006 10:56:55 +0200, Jesper Brunholm
<nospam@brunholm-scharff.dk> wrote:

>Kan nogen rette min regex, og gerne med forklaring?

Når du bruger e-modfieren til at afvikle PHP-kode med den matchede
tekst - og det gør du her:

    $pattern='/<'.$type.'>(.*)<\/'.$type.'>/Ue';
    $tekst = preg_replace($pattern, "$type('\\1')", $tekst);

... så bliver der afviklet addslashes til de matchede udtryk. Hvis du
holder dig til kun at bruge gåseøjne, kan du måske klare dig med at
rette nederste linje til:

    $tekst = preg_replace($pattern, '$type("\\1")', $tekst);

... idet det så ikke er noget problem at matchede gåseøjne får en gang
backslashes foran sig.

Generelt er PHPs PCRE-funktioner temmeligt klodsede i den retning,
sådan som de har valgt at implementere det.

Man kan dog undgå addslashes()-helvedet ved at bruge
preg_replace_callback() (med lidt omskrevet kode), hvilket i mange
tilfælde er at foretrække, hvis man risikerer at matche både ' og ".
Det er kun relevant, når man bruger e-flaget til sit regulære udtryk.

Det kræver dog en del mere kode, hvilket er irriterende i tilfælde,
hvor det ellers havde været i det regulæres udtryks ånd at referere
til de enkelte matchede dele i ét replace-udtryk.

preg_replace: http://php.net/preg-replace-callback

Et eksempel på den måske lidt uventede opførsel for preg_replace:

<?php
$string = <<<EOD
Foo ' Bar " Baz
EOD;
print preg_replace('/.*/e','"$0"',$string)."\n";
print preg_replace('/.*/e',"'$0'",$string)."\n";
?>

Dette outputter følgende:
Foo \' Bar " Baz
Foo ' Bar \" Baz

Måske ikke hvad man havde forventet.

--
- Peter Brodersen
Ugens^WMånedens^WSommerens værktøj - Find vej: www.findvej.dk
Nu med valgfri tekst: www.findvej.dk/Nybrogade2,1203?text=Kulturministeriet

Bertel Lund Hansen (09-08-2006)
Kommentar
Fra : Bertel Lund Hansen


Dato : 09-08-06 15:36

Peter Brodersen skrev:

> Generelt er PHPs PCRE-funktioner temmeligt klodsede i den retning,
> sådan som de har valgt at implementere det.

Jeg har kun sat mig meget nødtørftigt ind i regulære udtryk. Til
brug i en funktion har jeg lavet følgende:

function is_harmless   ($newentry plus flere parametre) {
   $harmless=array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');
   $harmful=array('@', '%', "\\", '/', '<', '>', '(', ')', ';', '!', ':', '"', "'", 'script');
   $lowcaseentry=strtolower($newentry);
   $newlowentry=str_replace($harmful,$harmless,$lowcaseentry);
   [en masse specialkode]
   return $newlowentry==$lowcaseentry;
}

Det synes jeger nemt at have med at gøre, men det er måske bare
min dovenskab?

--
Bertel
http://bertel.lundhansen.dk/      http://fiduso.dk/

Peter Brodersen (09-08-2006)
Kommentar
Fra : Peter Brodersen


Dato : 09-08-06 17:00

On Wed, 9 Aug 2006 16:35:56 +0200, Bertel Lund Hansen
<nospamfilius@lundhansen.dk> wrote:

>Jeg har kun sat mig meget nødtørftigt ind i regulære udtryk. Til
>brug i en funktion har jeg lavet følgende:
>
>function is_harmless   ($newentry plus flere parametre) {
>   $harmless=array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');
>   $harmful=array('@', '%', "\\", '/', '<', '>', '(', ')', ';', '!', ':', '"', "'", 'script');
>   $lowcaseentry=strtolower($newentry);
>   $newlowentry=str_replace($harmful,$harmless,$lowcaseentry);

For en god ordens skyld kan du erstatte $harmless med ''. Du behøver
ikke at have et array for hver entry, hvis de alligevel skal erstattes
med det samme:

http://php.net/str-replace
"If search is an array and replace is a string, then this replacement
string is used for every value of search."

Din søgning efter "script" synes jeg er lidt pudsig. Hvorfor ikke
eval, når du er i gang (hvilket i andre tilfælde har gået ud over
folk, som har snakket om "medieval" )

>Det synes jeger nemt at have med at gøre, men det er måske bare
>min dovenskab?

Det er også brugbart nok i dit tilfælde. Det er også let nok at lave
med et regulært udtryk, hvor man ikke kommer ud i at skulle lave andet
end simple søg&erstatninger.

Det komplekse opstår, når man vil tage dele af det matchede - uden at
kende det på forhånd - og så afvikle noget PHP-kode for denne
specielle del.

At finde alle tekststykker, der ligner telefonnumre, og markere dem
med fed, kan også gøres uden videre meget simpelt med regulære udtryk,
uden at skulle evaulere noget.

I det aktuelle tilfælde skal den matchede data (som man vel at mærke
ikke kender på forhånd) behandles, før den lægges tilbage igen. Her
kan eval/callback-funktionerne så være praktiske nok.

--
- Peter Brodersen
Ugens^WMånedens^WSommerens værktøj - Find vej: www.findvej.dk
Nu med valgfri tekst: www.findvej.dk/Nybrogade2,1203?text=Kulturministeriet

Jesper Brunholm (09-08-2006)
Kommentar
Fra : Jesper Brunholm


Dato : 09-08-06 20:16

Peter Brodersen skrev:
> Når du bruger e-modfieren til at afvikle PHP-kode med den matchede
> tekst - og det gør du her:
>
>     $pattern='/<'.$type.'>(.*)<\/'.$type.'>/Ue';
>     $tekst = preg_replace($pattern, "$type('\\1')", $tekst);
>
> .. så bliver der afviklet addslashes til de matchede udtryk. Hvis du
> holder dig til kun at bruge gåseøjne, kan du måske klare dig med at
> rette nederste linje til:
>
>     $tekst = preg_replace($pattern, '$type("\\1")', $tekst);

Det virkede helt efter hensigten, mange tak. Jeg troede ikke at den
ville parse $type når det stod i enkelte anførselstegn, men der gælder
åbenbart andre regler her.

mvh

Jesper Brunholm

Søg
Reklame
Statistik
Spørgsmål : 177501
Tips : 31968
Nyheder : 719565
Indlæg : 6408522
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste