[PHP] Regexp parameters uit string.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Optix
  • Registratie: Maart 2005
  • Laatst online: 12-08 19:46
Hi,

Ik heb de volgende string: "test[did=regexp,work=false]".
Dan wil ik mbv een regexp met de volgende array eindigen:
PHP:
1
    array('did' => 'regexp', 'work' => 'false');


Ben (nog steeds) lerende regexp, maar dit is wat ik nu heb:

PHP:
1
2
3
    $subject = "test[did=regexp,work=false]";       
    $result = preg_match("/\[(.*)=(.*)\]/", $subject, $matches);        
    print_r($matches);


Wat het volgende uitpoept:
code:
1
2
3
4
array
  0 => '[did=regexp,work=false]'
  1 => 'did=regexp,work'
  2 => 'false'


Ik moet zoiezo nog iets met die komma doen maar ik kom er niet helemaal uit.

.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

PHP:
1
$result = preg_match_all("/\[([^=]*)=([^,\]]*)\]/iU", $subject, $matches);

edit:
Scratch that, dat werkt niet. Ik zou dit ook niet met regexps doen, gewoon alles splitten op komma's en daarbinnen alles splitten op = werkt ook prima en is waarschijnlijk zelfs sneller.

[ Voor 54% gewijzigd door NMe op 14-10-2008 19:21 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Optix
  • Registratie: Maart 2005
  • Laatst online: 12-08 19:46
-NMe- schreef op dinsdag 14 oktober 2008 @ 19:20:
PHP:
1
$result = preg_match_all("/\[([^=]*)=([^,\]]*)\]/iU", $subject, $matches);
Resulteert:
code:
1
2
3
4
5
6
7
array
  0 => 
    array
  1 => 
    array
  2 => 
    array

.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Zie mijn edit. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Optix
  • Registratie: Maart 2005
  • Laatst online: 12-08 19:46
Ha, mja zo heb ik het dus ook opgelost, maar vind toch iets netter als het met 1 regexp KAN.

.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Het kan wel, maar het is, denk ik, trager en bovendien een stuk minder leesbaar.
PHP:
1
$result = preg_match_all("/\[(([^=]*)=([^,\]]*),?)\]*/iU", $subject, $matches);

Die werkt wel, denk ik. Maar nogmaals, het zou niet mijn voorkeur hebben.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Optix
  • Registratie: Maart 2005
  • Laatst online: 12-08 19:46
-NMe- schreef op dinsdag 14 oktober 2008 @ 19:29:
Het kan wel, maar het is, denk ik, trager en bovendien een stuk minder leesbaar.
PHP:
1
$result = preg_match_all("/\[(([^=]*)=([^,\]]*),?)\]*/iU", $subject, $matches);

Die werkt wel, denk ik. Maar nogmaals, het zou niet mijn voorkeur hebben.
Helaas, deze werkt ook niet :P
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
array
  0 => 
    array
      0 => '[did='
  1 => 
    array
      0 => 'did='
  2 => 
    array
      0 => 'did'
  3 => 
    array
      0 => ''

.


Acties:
  • 0 Henk 'm!

  • Optix
  • Registratie: Maart 2005
  • Laatst online: 12-08 19:46
Overigens, mijn huidige oplossing
PHP:
1
2
3
4
5
6
7
8
    $options = array();
    $result = preg_match("/\[(.*)\]/", $subject, $matches);
                            
    foreach (explode(',', $matches[1]) as $option) 
    {
        $option = explode('=', $option);
        $options[$option[0]] = $option[1];
    }


is 0.4 microseconde langzamer :P

.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Je hebt het probleem niet helemaal exact gedefinieerd, dus wat je precies voor eisen stelt weet ik niet.
Het volgende werkt met maar 1 regexp:
PHP:
1
2
3
4
$subject = 'test[did=regexp,work=false]';
preg_match_all('/([^[,=\]]*)=([^[,=\]]*)/', $subject, $matches);
$options = array_combine($matches[1],$matches[2]);
print_r($options);

Maar checkt gewoon de syntax niet...
Anders worden het toch al snel meerdere regexpen, of een andere oplossing. :)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Optix
  • Registratie: Maart 2005
  • Laatst online: 12-08 19:46
Klopt, ik had mijn eisen dan ook net wat aangepast mbt de sepperator zoals je ziet :P
PHP:
1
2
3
4
if (preg_match("/\[(.*)\]/", $subject, $matches)) 
{
    parse_str($matches[1], $options);
}

.


Acties:
  • 0 Henk 'm!

Verwijderd

Optix schreef op dinsdag 14 oktober 2008 @ 19:23:
Ha, mja zo heb ik het dus ook opgelost, maar vind toch iets netter als het met 1 regexp KAN.
Tja, m.i. kunnen "netjes" en "regexp" in 1 regel alleen maar als er een ontkenning tussen staat. ;)
Tikkie gechargeerd natuurlijk, maar vaak wanneer een string geparsed moet worden zie je allerlei ingewikkelde, onleesbare 'bend over backwards' regexen, terwijl meestal een simpel parsertje (al dan niet stack based) 't ook prima doet en vaak beter performt.
Voordeel van zo'n parsertje is dat jij en jouw collega's na een paar maand nog direct kunnen zien wat 't ding doet, terwijl je bij een uitgebreide regex je al na een week afvraagt wat 'ie doet en waarom. (goed commenten helpt dan wel, maar je comment heeft dan waarschijnlijk evenveel regels als die parser...)

Regexps gebruik ik niet of nauwelijks in m'n code, maar wel veelvuldig in grep, awk, sed etc. scripts, en daar is 't hardstikke handig. Maar (alweer m.i.) is in een applicatie een regex die niet snel te vatten is niet handig. Een parsertje is dan prettiger, ook voor je collega's.

"you are not supposed to understand this" (uit Janoz' signoff geloof ik) is leuk voor 't ego van de maker, maar staat onderhoud van de applicatie gigantisch in de weg.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
pedorus schreef op dinsdag 14 oktober 2008 @ 20:00:
Anders worden het toch al snel meerdere regexpen, of een andere oplossing. :)
Wat een onzin, het kan prima met een:
PHP:
1
2
3
4
5
6
$subject = "test[did=regexp,work=false]";
if (preg_match_all('/(?:^[^[]*\[|(?<!^)\G,)([^=]*)=([^,]*)(?=(?:,[^=]*=[^,]*)*]$)/', 
                   $subject, $matches)) {
    $options = array_combine($matches[1],$matches[2]);
    print_r($options);
}

Comments zijn ook niet nodig, want iedereen snapt de details toch? :+
Some people, when confronted with a problem, think
“I know, I'll use regular expressions.” Now they have two problems.
:) (source)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

Verwijderd

dit is trouwens een goed boek over regular expressions

Acties:
  • 0 Henk 'm!

Verwijderd

pedorus, I rest my case. :)
Dank voor je hilarische voorbeeld.

Acties:
  • 0 Henk 'm!

  • chris
  • Registratie: September 2001
  • Laatst online: 11-03-2022
Het is nog iets simpeler te doen volgens mij:
  1. letterlijke "[": \[
  2. Vervolgens komt er een "key=value": ([^=]*)=([^,]*)
  3. Daarna komt een lijst van ",key=value": (,([^=]*)=([^,]*))*
  4. En vervolgens een vierkante haak sluiten: \]
Dus de volgende preg-expression

code:
1
/\[([^=]*)=([^,]*)(,([^=]*)=([^,]*))*\]/


Je moet alleen het derde element uit de array gooien:
Parenthesized substring matches:

    * substring 1: did
    * substring 2: regexp
    * substring 3: ,work=false
    * substring 4: work
    * substring 5: false


Maar eigenlijk is het natuurlijk gewoon veel mooier met een "normale" functie zoals hierboven.

Acties:
  • 0 Henk 'm!

  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 08-07 14:27
chris schreef op donderdag 16 oktober 2008 @ 01:16:
Het is nog iets simpeler te doen volgens mij:
  1. letterlijke "[": \[
  2. Vervolgens komt er een "key=value": ([^=]*)=([^,]*)
  3. Daarna komt een lijst van ",key=value": (,([^=]*)=([^,]*))*
  4. En vervolgens een vierkante haak sluiten: \]
Dus de volgende preg-expression

code:
1
/\[([^=]*)=([^,]*)(,([^=]*)=([^,]*))*\]/


Je moet alleen het derde element uit de array gooien:
Parenthesized substring matches:

    * substring 1: did
    * substring 2: regexp
    * substring 3: ,work=false
    * substring 4: work
    * substring 5: false


Maar eigenlijk is het natuurlijk gewoon veel mooier met een "normale" functie zoals hierboven.
code:
1
/\[([^=]*)=([^,]*)(?:,([^=]*)=([^,]*))*\]/


Toegevoegd: ?: Als je dat na een open haakje zet worden deze non-capturing.

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
chris schreef op donderdag 16 oktober 2008 @ 01:16:
Het is nog iets simpeler te doen volgens mij:
  1. letterlijke "[": \[
Je hebt gelijk, bij mij kan "^[^[]*" weg, omdat we alles toestaan nu. Ik kan me enkel voorstellen dat je later dingen als "foutbegin[,,][a=b]" wil uitsluiten, door komma's in de keys niet toe te staan.
Dus de volgende preg-expression

code:
1
/\[([^=]*)=([^,]*)(,([^=]*)=([^,]*))*\]/


Je moet alleen het derde element uit de array gooien:
Parenthesized substring matches:

    * substring 1: did
    * substring 2: regexp
    * substring 3: ,work=false
    * substring 4: work
    * substring 5: false
Dat derde element is simpel weg te halen (zie boven). Het probleem is enkel dat deze methode niet werkt als je meer dan 2 key-value-pairs hebt. Dan worden match 3&4 steeds overschreven...
En ik neem aan dat je tot het einde wil matchen, voor de syntax-check. Voorbeeld van mogelijke fout: "a[a=b][c=d,]"

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1