[PHP] Hoe begin en eind geven in patern voor preg_replace?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Ik heb bijvoorbeeld een volgende zoekopdracht voor mijn te schrijven eenvoudige zoekmachine op mijn eigen website:
woord "dit is een test" en "dit is er nog zo eentje"

Nu wil ik graag dat groepen die met een quote worden begonnen en geëindigd er apart uit worden gehaald en ook als groep in de database opgezocht worden.
Ik had geen idee hoe ik dat moest doen, maar dacht er aan om eerst de groepen er uit te filteren, die in ene array opslaan, telkens de string korter maken door een str_replace uit te voeren op de string met een groep en dan de losse woorden aan de array waar de groepen al in zitten toevoegen.

Dus:
eerst worden de groepen dit is een test en dit is er nog zo eentje er uit gevist in een array $zoeken gezet
Vervolgens wordt de groep uit de originele zoekstring gehaadl waardoor de zoekstring nu woord en is.
Daarna wordt deze overgebleven zoekstring geëxplode op de spatie en toegevoegd aan de array $zoeken.
Ten slotte wordt voor elke value in de array $zoeken een LIKE in de zoekquery toegevoegd en de totale zoekquery uitgevoerd.

Ik zit echter met het probleem hoe ik dit exact voor elkaar krijg en blijf vooral hangen op het filteren van de groepen uit een zoekstring.
Met mijn huidige code pakt PHP namelijk alles tussen de allereerste quote en de allerlaatste quote en vind ie dus maar 1 groep (met in het midden 2 quotes) terwijl er eigenlijk 2 groepen zijn. Ik heb al even wat documentatie over regulaiere expressies gelezen, maar kom er niet uit.
De documentatie zegt ^het begin van regel is en $ het einde, maar dit is in dit geval niet echt van toepassing.
Ook wordt er in gezegd dat \A de start van ene tekst aan geeft en \Z het einde van een tekst, maar ook dit haalt niets uit.

Weet iemand voor mij de juiste methode?

Dit is mijn script nu:
PHP:
1
2
3
4
5
6
7
8
9
<?php
$patern = "/(\"(.*)\")*?/";
$tekst = "woord \"dit is een test\" en \"dit is er nog zo eentje\"";
preg_match($patern,$tekst,$matches);
echo "<pre>";
echo "<b>Input:</b>\n".$tekst."\n\n<b>Matches-array:</b>\n";
print_r($matches);
echo "</pre>";
?>

Acties:
  • 0 Henk 'm!

  • MatHack
  • Registratie: Oktober 2001
  • Niet online

MatHack

Dev by day, Gamer by night

Maak een RegEx die maar één string tussen quotes pakt en kijk dan eens naar http://php.net/preg_match_all

EDIT:
Ben in een goede bij vandaag, hier is je RegEx die je dan zou moeten gebruiken:
code:
1
/\"(.+?)\"/


Typfouten voorbehouden.

[ Voor 45% gewijzigd door MatHack op 27-02-2004 16:14 ]

There's no place like 127.0.0.1


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Ja dat is em inderdaad. Ik had in plaats van ene plusje nog een sterretje geprobeerd. Maar ik had alleen maar preg_match ipv preg_match_all gebruikt. Nu krijg ik dus wel alle gevonden groepen.

Ik denk dat ik nu in ieder geval weer een heel end vooruit kom. :)

Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Omdat ik verliefd ben op assertions in PCRE ben ik in een nog veel betere bui O+

PHP:
1
2
3
4
5
6
$str = 'Dit is een "string met quotes" en nog meer';
$str .= ' "quotes enzo" en nog !@#$ wat .,<> gekke tekens';
$str .= ' en nog 1 zonder "matchende eindquote. ';

preg_match_all ( '/(\b(?!")\S+\b)|("([^"]+)")/', $str, $match );
print_r ( $match );


:Y)

edit:
PHP:
1
preg_match_all ( '/(\b(?!")\S+\b)|(?:"([^"]+)")/', $str, $match );
scheelt weer een nutteloze captured group :)

[ Voor 16% gewijzigd door drm op 27-02-2004 16:30 ]

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
drm schreef op 27 februari 2004 @ 16:27:
Omdat ik verliefd ben op assertions in PCRE ben ik in een nog veel betere bui O+

PHP:
1
2
3
4
5
6
$str = 'Dit is een "string met quotes" en nog meer';
$str .= ' "quotes enzo" en nog !@#$ wat .,<> gekke tekens';
$str .= ' en nog 1 zonder "matchende eindquote. ';

preg_match_all ( '/(\b(?!")\S+\b)|("([^"]+)")/', $str, $match );
print_r ( $match );


:Y)

edit:
PHP:
1
preg_match_all ( '/(\b(?!")\S+\b)|(?:"([^"]+)")/', $str, $match );
scheelt weer een nutteloze captured group :)
Zou je ook zo lief willen zijn om uit te leggen wat deze expressie exact doet? O+
Filterd deze op verkeerde tekens en dergelijke? En zorgt deze er voor dat daar waar ik een uiteindelijke string nog zou exploden op spaties om de laatste woorden er uit te halen en toe te voegen aan de array met groepen dit door de preg_match_all met deze expressie al gedaan wordt?

Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Ow ja, ik zie het al. Ik heb het even geprobeerd...
Dit is het resultaat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Array
(
    [0] => Array
        (
            [0] => Dit
            [1] => is
            [2] => een
            [3] => "string met quotes"
            [4] => en
            [5] => nog
            [6] => meer
            [7] => "quotes enzo"
            [8] => en
            [9] => nog
            [10] => wat
            [11] => gekke
            [12] => tekens
            [13] => en
            [14] => nog
            [15] => 1
            [16] => zonder
            [17] => matchende
            [18] => eindquote
        )

    [1] => Array
        (
            [0] => Dit
            [1] => is
            [2] => een
            [3] => 
            [4] => en
            [5] => nog
            [6] => meer
            [7] => 
            [8] => en
            [9] => nog
            [10] => wat
            [11] => gekke
            [12] => tekens
            [13] => en
            [14] => nog
            [15] => 1
            [16] => zonder
            [17] => matchende
            [18] => eindquote
        )

    [2] => Array
        (
            [0] => 
            [1] => 
            [2] => 
            [3] => string met quotes
            [4] => 
            [5] => 
            [6] => 
            [7] => quotes enzo
            [8] => 
            [9] => 
            [10] => 
            [11] => 
            [12] => 
            [13] => 
            [14] => 
            [15] => 
            [16] => 
            [17] => 
            [18] => 
        )

)

Dus alle "losse woorden" zal ik dus uit key 1 moeten halen en alle "groepen" uit key 2.
Dat werkt inderdaad wel handiger. :)
Onwijs gaaf bedankt drm! Kusje! :> :+

[ Voor 22% gewijzigd door Joen op 27-02-2004 17:47 ]


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

idd :) Voor het gemak zou je nog even een functie kunnen schrijven die de arrays combineert. Degene die goed kijkt ziet namelijk dat waar de values van de tweede array leeg zijn, ze in de 3e array wel zitten. Helaas biedt php daar zelf geen handige functie voor (afaik?), maar als je de arrays combineert ben je gauw klaar :)

De regex zit als volgt in elkaar:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/
   (
      \b       # assert op word boundary. (1)
      (?!")    # een negative lookahead assertion op een quote (1)
      \S+      # match alle volgende non-whitespace characters ...
      \b       # ...gevolgd door een word-boundary (3)
   )
|              # alternation (4)
   (?:         # non-captured group (5)
      "(       # match een quote en start de captured group (6)
         [^"]+ # match alles totaan de eerst volgende quote (7)
      )"       # sluit de captured group en match de sluitquote (8)
   )
/x


[list=1]• Allereerst betekent assertion dat je iets van een bepaalde soort op die plek wilt hebben. Je matcht er niet fysiek op. Om dat echt te begrijpen moet je er een beetje mee gaan spelen.
Een word-boundary assertion betekent dat er op de plek van de \b van een 'word' naar een 'non-word' character gesprongen wordt, of andersom. Wat een word precies is kun je in de manual terugvinden
• Een negatieve lookahead assertion betekent eigenlijk dat je wilt voorkomen dat hetgeen na die assertion komt voldoet aan de expressie die je in die assertion zet. Het heeft de volgende vorm: (?!expressie). In dit geval wil je dus voorkomen dat er een quote staat op de plek van de (eerste) character die op \S+ (de eerstvolgende expressie) matcht.
• Vervolgens wil je dat alles wat non-whitespace is wel matcht (\S+), zolang het maar weer van word naar non-word springt aan het eind. Dat betekent feitelijk gewoon dat je alleen "words" toestaat.
• Alternation betekent gewoon een 'of/of' situatie. Je wilt alterneren tussen woorden en gequote strings.
• Een non captured group gebruik je als je de groep als zodanig later niet meer wilt gebruiken (of aan refereren), maar je wel structuur aan wilt geven in je regular expression. Hij staat hier vermeld vanwege de alternation.
• Dit lijkt me wel duidelijk. Je wilt pas na de quote de captured group starten vanwege de inhoud van de string
• Dit is ook wel duidelijk: match 1 of meer keer (+) alle characters die geen quote zijn ([^"])
• Om dezelfde reden als genoemd bij 6 sluit je de captured group weer af voor de quote

Dat is het eigenlijk :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
euhm, array element 0 is toch een combinatie van 1 en 2?

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Grijze Vos:
euhm, array element 0 is toch een combinatie van 1 en 2?
Nee, je kijkt over de quotes heen ;) Daarom zit die capturing group ertussen om te zorgen dat je niet achteraf de quotes er nog 's uit moet filteren.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


Acties:
  • 0 Henk 'm!

  • Joen
  • Registratie: Juli 2003
  • Laatst online: 09-08 18:34
Bedankt voor de heldere uitleg drm, alhoewel het voor mij toch een beetje mn petje te boven gaat.
Maar ik probeer het wel te begrijpen en verdiep er waar nodig zo af en toe wel in.
Het belangrijkste is dat jouw oplossing me dusdanig geholpen heeft dat ik mijn pagina af heb kunnen maken. :)

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Nee, je kijkt over de quotes heen ;) Daarom zit die capturing group ertussen om te zorgen dat je niet achteraf de quotes er nog 's uit moet filteren.
Nou je het zegt ;)

[ Voor 4% gewijzigd door Grijze Vos op 27-02-2004 20:07 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info

Pagina: 1