[PHP/regex] alles tussen [ en ] matchen

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

  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Ik wil een variabele meegeven aan een functie, die er bijvoorbeeld zo uit ziet:
PHP:
1
2
3
<?
    $blaat = "hoi melp <guru> [doed] errrhmnee [id][jaja] duh hoii";
?>

Nu is de bedoeling dat die functie alles wat tussen [ en ] staat eruit sloopt, en in een array dumpt. Ik heb aardig zitten kloten met preg_match, maar ik kwam er niet echt uit. Dit is wat ik had verzonnen:
PHP:
1
2
3
4
5
6
<?
    preg_match_all("/\\[.[a-zA-z0-9]+\]/i",$blaat,$matches);
    foreach ($matches[0] as $key => $value) {
        print "$key = $value<br>";
    }
?>

Maar nu stopt hij [doed] in $matches (dat is dus goed), en [id][jaja], maar dat moet dus [id] en [jaja] zijn (los dus).

Hoe ga ik dat voor elkaar krijgen?

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

code:
1
/\\[[^\]+\]/

gebruik btw.
PHP:
1
2
3
<?
print_r ( $matches )
?>

om te zien hoe zo'n matches-array precies in elkaar zit

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


  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Op maandag 17 december 2001 12:20 schreef drm het volgende:
code:
1
/\\[[^\]+\]/

gebruik btw.
PHP:
1
2
3
<?
print_r ( $matches )
?>

om te zien hoe zo'n matches-array precies in elkaar zit
Eurhm:
Warning: Compilation failed: missing terminating ] for character class at offset 9 on line 3

Warning: Invalid argument supplied for foreach() on line 4
Dis de volledige code:
code:
1
2
3
4
5
    $blaat = "hoi melp <guru> [doed] errrhmnee [id][jaja] duh hoii";
    preg_match_all("/\\[[^\]+\]/",$blaat,$matches);
    foreach ($matches[0] as $key => $value) {
      print "$key = $value<br>";
    }

Foutje?

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

code:
1
/\\[([^\]]+?)\]/

Lijkt me zo beter ;)

  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Hmm zo te zien bedoelde je dit:
code:
1
/\\[[^\]]+\]/

Kun je 'm even stap voor stap uitleggen? Wellicht dat ik er dan ook enigszins wat inzicht in ga verkrijgen...

  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Op maandag 17 december 2001 12:26 schreef ACM het volgende:
code:
1
/\\[([^\]]+?)\]/

Lijkt me zo beter ;)
Werkt ook :)
Ik heb wat regex-documentation zitten bekijken, maar ik kan 'm geloof ik nog niet helemaal analyseren.

/edit
Met name dit vat ik nog nie helemaal:
code:
1
[([^\]]+?)

  • dusty
  • Registratie: Mei 2000
  • Laatst online: 21-02 00:06

dusty

Celebrate Life!

Op maandag 17 december 2001 12:16 schreef Pelle het volgende:
PHP:
1
2
3
4
5
6
<?
    preg_match_all("/\\[.[a-zA-z0-9]+\]/i",$blaat,$matches);
    foreach ($matches[0] as $key => $value) {
        print "$key = $value<br>";
    }
?>
A-z zijn HEEEEEL veel karakters :+ (case sensitive!)

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


  • Spleasure
  • Registratie: Juli 2001
  • Laatst online: 26-08 09:10

Spleasure

Ik hier?

Het zorgt ervoor dat in value geen ] voor mag komen

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Ok, uitleg:
code:
1
/\\[([^\]]+?)\]/


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
- // -> snap je?
- \\[ ... \] pak een [ en een ] (afhankelijk van de "zooi" 
ertussen wordt er bijvoorbeeld de 3e, 1e of zelfs laatste 
gepakt)
- ([^\]]+?)
- - [^\]] ziet er eng uit, maar betekend gewoon "elk teken 
dat geen (^) ] (\]) is". Waarbij de [] de "class" 
beschrijven.
- - de [...]+ betekend "pak 1 of meer uit die characterclass
(beschreven door datgene wat binnen de [] staan)"
- - De +? betekend dan nog zoiets als "zodra je een match
 hebt, niet verder zoeken naar een betere match" (dus niet 
->[ .....][ ....]<- ->[.....]<- maar gelijk de eerste pakken)

Excuses voor de code-tag, maar topix wist overal leuke smilies tussen te stoppen |:(
Volgens mij was dat het wel :)

[edit]
Dit is trouwens niet helemaal correcte uitleg, maar dan vooral om voorbij te gaan aan allerlei details die je denk ik al wist :)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

ACM:
code:
1
/\\[([^\]]+?)\]/
die +? is dus een soort "anti-greediness"-manier ? Kende ik nog niet. Wel handig *D
Pelle:
Hmm zo te zien bedoelde je dit:
code:
1
/\\[[^\]]+\]/
Klopt :)

* drm was weer eens te snel... |:(

stap voor stap:
• / begin regex
• \ escape volgende karakter
• [ "match-self" karakter (deze wil ik tegenkomen). Moet je escapen
• [ Bepaal een groep karakters die mogen matchen
• ^ "Alles behalve" wat volgt
• \ escape volgende karakter
• ] is dus de daadwerkelijke groep karakters die niet voor mag komen
• ] einde groep karakters
• + De groep moet 1 of meer keer voorkomen
• \ escape volgende karakter
• ] "match-self" deze komt aan het eind.
• / einde regex

In het kort:
[(alles wat niet ']' is)]

Het verwarrende in deze regex is dat '[' en ']' dus speciale karakters zijn in een regex en dus geescaped moeten worden :)

hth :?

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


  • dusty
  • Registratie: Mei 2000
  • Laatst online: 21-02 00:06

dusty

Celebrate Life!

en toen zat er een [ bug in de regexp ;)

Back In Black!
"Je moet haar alleen aan de ketting leggen" - MueR


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op maandag 17 december 2001 13:06 schreef drm het volgende:
die +? is dus een soort "anti-greediness"-manier ? Kende ik nog niet. Wel handig *D
Yupz :)

Trouwens, jouw regexp matched wel, maar geeft geen waarden terug :P aangezien je niet met () werkt ;)

Ow, pelle, als je _alle_ [] blokken wilt hebben moet je even preg_match_all gebruiken.

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op maandag 17 december 2001 13:12 schreef dusty het volgende:
en toen zat er een [ bug in de regexp ;)
Owwww, vast wel.

Bedoel je dat [bla[bla] niet zo mooi gematched wordt?

  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Op maandag 17 december 2001 13:06 schreef drm het volgende:
stap voor stap:
• ^ "Alles behalve" wat volgt
Daar ging ik dus de mist in.
Van PHPBuilder:
First of all, let's take a look at two special symbols: '^' and '$'. What they do is indicate the start and the end of a string [..]
Of sla ik hier even een denkstap over?

Enniewee, de reden dat ik dit wou weten is het volgende. Er moet een lijst met results komen, maar ik weet alleen nog niet in welke layout dat moet komen. En toen dacht ik, laat ik daar eens een class voor schrijven, waar je een string mee kunt geven die de opmaak van de results bepaalt.
Het is misschien wel een beetje een vergezochte oplossing in dit geval, maar aangezien ik verwacht dat het in de toekomst nog wel eens nuttig kan zijn ben ik er toch maar aan begonnen.
PHP:
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
<?
    class vacatureLijst {
        
        function vacatureLijst($server,$username,$password,$db) {
            $this->server   = $server;
            $this->username = $username;
            $this->password = $password;
            $this->db       = $db;
        }
        
        function connect() {
            mysql_connect  ($this->server, $this->username, $this->password) or die("Kan geen verbinding maken met server");
            mysql_select_db($this->db)                                       or die("Kan database niet selecteren");
        }
        
        function performQuery($query) {
            $this->query = mysql_query($query);
        }
        
        function getRow($rowFormat) {
            preg_match_all("/\\[([^\]]+?)\]/",$rowFormat,$matches);
            foreach ($matches[0] as $key => $value) {
                $matches[0][$key] = str_replace("[", "", $matches[0][$key]);
                $fields[$key]     = str_replace("]", "", $matches[0][$key]);
            }
            while ($this->result = mysql_fetch_array($this->query)) {
                foreach ($fields as $key2 => $value2) {
                    print $this->result[$value2] . " ";
                }
                print "<br>";
            }
        }
    }
    $vacList = new vacatureLijst("euhmnee","nope","njet","guessnot");
    $vacList->connect();
    $vacList->performQuery("SELECT * FROM vacatures");
    $vacList->getRow("ID = [id]<br> <b>[titel]</b> [omschrijving]");
?>

Dit werkt; ik had ook meteen de vraag kunnen stellen die ik nu ga doen, maar het leek me verstandiger om het stap voor stap aan te pakken (en het niet de schijn van een scriptrequest heeft :)):

Hoe krijg ik het voor elkaar dat dit:
code:
1
ID = [id]<br> <b>[titel]</b> [omschrijving]

..vervangen wordt door dit?
code:
1
ID = " . $this->result[id] . "<br> <b>" . $this->result[titel] . "</b> " . $this->result[omschrijving]

Nogmaals, het zal voor de meesten van jullie waarschijnlijk wat rommelig over komen, maar ik probeer dus zelf iets generieks te bouwen dat dus erg makkelijk hergebruikt kan worden & waar ik zelf ook nog eens wat van geleerd heb :)

Wie schopt mij in de goeie richting?

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Pelle:
Daar ging ik dus de mist in.
Van PHPBuilder:
...
Klopt ook wel, maar dan praat je niet over een klasse-bepaling (zo heet dat toch?), oftewel, die ^ buiten een '[...]' bepaling betekent "begin van de string", en is dus alleen geldig wanneer hij daadwerkelijk aan het begin van de string staat. Anders moet je hem (dacht ik, weet ik niet zeker) escapen.

Wanneer hij als eerste karakter in zo'n '[...]' bepaling staat betekent dat bijv waar [A-Z] alle karakters van A-Z matcht [^A-Z] alle karakters die niet in de reeks A-Z voorkomen matcht.
Of sla ik hier even een denkstap over?
nope is gewoon beetje "ambigu"
Hoe krijg ik het voor elkaar dat dit:
code:
1
2
3
ID = [id]<br> 
<b>[titel]</b> 
[omschrijving]

..vervangen wordt door dit?
code:
1
2
3
ID = " . $this->result[id] .
"<br> <b>" . $this->result[titel] . 
"</b> " . $this->result[omschrijving]

Nogmaals, het zal voor de meesten van jullie waarschijnlijk wat rommelig over komen, maar ik probeer dus zelf iets generieks te bouwen dat dus erg makkelijk hergebruikt kan worden & waar ik zelf ook nog eens wat van geleerd heb :)

Wie schopt mij in de goeie richting?
ik zou het zo aanpakken:
code:
1
preg_replace ( "/\\[([^\]]+?)\]/e", "$result [ '\\1' ]", $string );

die 'e' modifier na de laatste slash in je regex betekent dat het 2e argument van de preg_replace-aanroep niet als waarde maar als evalueerbare code gezien wordt. Je kunt daar dus ook bijvoorbeeld een functie aanroep in zetten:
code:
1
preg_replace ( "/\\[([^\]]+?)\]/e", "getVar ( $this, '\\1' );", $string );


code:
1
2
3
4
5
6
7
function getVar ( $obj, $varName )
{
   return 
    isset ( $obj->result [ $varName ] ) 
    ? $obj->result [ $varName ]
    : "";
}

snappie het een beetje?

voor het werken met \\1, \\2 etc verwijs ik je naar de manual.

.

.
ACM:
Trouwens, jouw regexp matched wel, maar geeft geen waarden terug :P aangezien je niet met () werkt ;)
heb je gelijk in :)

edit: oopzie! typo

edit2: oopzie2! typo2

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


  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Samen met de immer behulpzame drm even via ICQ verder aan het klooien, maar 't wil nog niet echt vlotten.

Deze functie zou moeten werken:
PHP:
1
2
3
4
5
6
7
<?
        function getRow($rowFormat) {
            while ($this->result = mysql_fetch_array($this->query)) {
                print preg_replace ("/\\[([^\]]+?)\]/e", "$result['\\1']", $rowFormat);
            }
        }
?>

Maar dat doet hij niet. Zie hier de volledige source.
Dit is de foutmelding:
Parse error: parse error, expecting `'('' in Unknown on line 0

Fatal error: Failed evaluating code: Array['id'] in vacatures.php on line 27
Waarbij line 27 die preg_replace is. Alle velden bestaan in de database, en zijn voor meerdere rijen gevuld.

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

* drm was alleen niet zo snugger te zien dat je bij een //e regex beter enkele quotes kunt gebruiken
PHP:
1
2
3
4
5
6
7
<?
        function getRow($rowFormat) {
            while ($this->result = mysql_fetch_array($this->query)) {
                print preg_replace ("/\\[([^\]]+?)\]/e", '$this->result["\\1"]', $rowFormat);
            }
        }
?>

Waarom?
Omdat bij enkele quotes de $ niet geparsed wordt... stom maar simpel en waar.

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


  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
* drm wist het al

Dit:
PHP:
1
2
3
<?
print preg_replace ("/\\[([^\]]+?)\]/e", "$this->result['\\1']", $rowFormat);
?>

moest worden:
PHP:
1
2
3
<?
print preg_replace ("/\\[([^\]]+?)\]/e", '$this->result["\\1"]', $rowFormat);
?>

De single en double quotes moesten omgedraaid worden. Thanks allot doed, kom binnenkort maar een keertje Shrek bij me kijken ofzow :)

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Pelle:
Thanks allot doed, kom binnenkort maar een keertje Shrek bij me kijken ofzow :)
Als we dat nou na oud en nieuw doen, kan ik zonder schroom zeggen: "Met bier!" ;)

maar da's een deal

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


  • Pelle
  • Registratie: Januari 2001
  • Laatst online: 18:23

Pelle

🚴‍♂️

Topicstarter
Op maandag 17 december 2001 14:33 schreef drm het volgende:
Als we dat nou na oud en nieuw doen, kan ik zonder schroom zeggen: "Met bier!" ;)

maar da's een deal
Voor jou haal ik altijd bier in huis, ook vóór oud en nieuw :+

/ot
hoe laat moeten jullie voetballen vanavond? misschien dat ik vroeg weg kan sneaken tijdens college

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Pelle:
/ot
hoe laat moeten jullie voetballen vanavond? misschien dat ik vroeg weg kan sneaken tijdens college
ICQ verder? ;)

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

Pagina: 1