[regexp] String splitten op , - maar niet tussen haakjes

Pagina: 1
Acties:

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 26-05 15:19

chem

Reist de wereld rond

Topicstarter
Ik heb een string; zeg

PHP:
1
$string = "Waa, Woe, IF(X, '1', true), Dus";


Die wil ik splitten op de komma, maar niet als hij tussen haakjes staat.

met /[^\)]+,[^\(]+/s kom ik eigenlijk geen steek verder :|

Klaar voor een nieuwe uitdaging.


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Het enige wat ik zo gauw kan bedenken is de string tussen haakjes vervangen door iets, en dat later terug zetten.

Alternatief:
splitsen van een string tot '(' en onthouden welk element de laatste is.
vervolgens ga je verder tot ')' en stop dat bij dat element,
en dan de rest splitsen, waarbij het eerste stukvoor de komma ook weer bij dat element hoort.
Drie deelproblemen. En als je haakjes binnen haakjes hebt, gaat dat automagisch goed.

edit:
OK, maar ik ben niet zo'n reguliere expressies held.

[ Voor 70% gewijzigd door Voutloos op 15-01-2004 16:01 ]

{signature}


  • chem
  • Registratie: Oktober 2000
  • Laatst online: 26-05 15:19

chem

Reist de wereld rond

Topicstarter
Dan kan ik net zo goed een char-by-char scanner maken en een (-teller bijhouden... en dat vind ik ruk, en traag :P

Klaar voor een nieuwe uitdaging.


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

1e poging:

PHP:
1
2
3
4
5
$string = "Waa, Woe, IF(X, '1', true), Dus";

preg_match_all('/(?:\s*)(([^(,]|\(.*?\))+)(?:,?\s*)/',$string,$array);

print_r($array[1]);


echter als je dit soort dingen hebt:

PHP:
1
$string = "Waa, Woe, IF(X, '(blaat)', true), Dus";


dan ga je natuurlijk weer de mist in...

Intentionally left blank


  • chem
  • Registratie: Oktober 2000
  • Laatst online: 26-05 15:19

chem

Reist de wereld rond

Topicstarter
Helaas, meerdere haakjes komen voor :|

Klaar voor een nieuwe uitdaging.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 26-05 00:01

Janoz

Moderator Devschuur®

!litemod

Puur theoretisch bekeken moet een tokenizer sneller werken dan een regexp. Een reguliere expresse zal immers ook tekentje voor tekentje moeten gaan matchen. Maar jij werkt natuurlijk weer met php ;).. Ik zou persoonlijk toch gewoon een tokenizer maken (geen char voor char scanner, maar mbv findFirst achtige functies) die zoekt op ( , en ) en inderdaad een tellertje.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

volgens mij heeft PHP ook geen functie die de 1e occurance uit een verzameling karakters in een string kan vinden, dus ik denk dat je toch karakter voor karakter moet gaan matchen en een soort stack moet gaan bouwen om ( ) en ' ' combo's met daarbinnen komma's uit te filteren. Nog lastiger wordt het als je ook met escape-tekens voor ' gaat werken; ook dat moet je gaan bijhouden.

Intentionally left blank


  • El_kingo
  • Registratie: Mei 2002
  • Laatst online: 17-03-2025
Hmm, dit lijkt mij een uitermate moeilijk probleem, maar misschien dat je iets kunt met zgn. assertions (zie ook : http://nl.php.net/manual/en/pcre.pattern.syntax.php onder Assertions)
voorbeeldje (niet getest):
code:
1
2
3
<?php
$arr = preg_split("/(?<!\([^\)]*),/", $string);
?>

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Nog een poging:

PHP:
1
2
3
4
5
6
7
8
$string = "Waa, Woe, IF(X, '((\\'(1))', true), Dus";

echo $string.'<br /><pre>';

preg_match_all('/(?:\s*)(([^(,\']|\'([^\\\]|\\\\\'?)*?\'|\(([^\']|\'([^\\\]|\\\\\'?)*?\')*?\))+)(?:,?\s*)/',$string,$array); 

print_r($array[1]);
echo '</pre>';


:P

Intentionally left blank


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

drm

f0pc0dert

crisp:
volgens mij heeft PHP ook geen functie die de 1e occurance uit een verzameling karakters in een string kan vinden, dus ik denk dat je toch karakter voor karakter moet gaan matchen en een soort stack moet gaan bouwen om ( ) en ' ' combo's met daarbinnen komma's uit te filteren.
Welnee, die stack heb je helemaal niet nodig. Je doet toch niets met karakters die niet binnen de haakjes staan, je hoeft niets te evalueren of wat dan ook. Gewoon een for-lusje met een tellertje voor de haakjes. Als het tellertje 0 is en je komt een komma tegen, de verzamelde string in een array stoppen en anders verder gaan. Even uit de losse pols:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$braces = 0;
$tmp_str = '';
$array = array ();
for ( $i = 0; $i < strlen ( $str ); $i ++ ) {
   $ch = $str {$i};
   if ( $ch == '(' ) {
      $braces ++;
   } else if ( $ch == ')' ) {
      $braces --;
   } else if ( $ch == ',' && $braces <= 0 ) { 
      // of $braces == 0, maar net hoe 'slim' je de splitter wilt maken
      $array[]= $tmp_str;
      $tmp_str = '';
      continue;
   }
   $tmp_str .= $ch;
}
if ( strlen ( $tmp_str ) ) {
   $array []= $tmp_str;
}
Nog lastiger wordt het als je ook met escape-tekens voor ' gaat werken; ook dat moet je gaan bijhouden.
Dat is een kwestie van states bijhouden. "ik zit in een string", "ik zit niet in een string", en alleen van de een naar de ander springen als de vorige character geen escape character was (bool)

Da's echt zo lastig allemaal niet, hoor, valt best wel mee. Hell, ik denk dat je zo'n functie sneller geschreven hebt dan een regex ervoor verzonnen hebt :P

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


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

drm schreef op 16 januari 2004 @ 13:41:
[...]
Da's echt zo lastig allemaal niet, hoor, valt best wel mee. Hell, ik denk dat je zo'n functie sneller geschreven hebt dan een regex ervoor verzonnen hebt :P
mwa, die regexp hierboven kostte me 15 minuten geloof ik ;)

ik denk alleen dat als ik er morgen weer naar kijk ik weer 15 minuten nodig heb om 'm te snappen, en als er dan nog een bug inzit of het toch anders moet, dan ben ik ws nog langer bezig...

[ Voor 23% gewijzigd door crisp op 16-01-2004 13:59 ]

Intentionally left blank


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

drm

f0pc0dert

crisp:
mwa, die regexp hierboven kostte me 15 minuten geloof ik ;)
Thank you for making my point :Y) :+

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


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

drm schreef op 16 januari 2004 @ 13:59:
[...]
Thank you for making my point :Y) :+
Ik typ gewoon langzaam :P

Intentionally left blank


  • chem
  • Registratie: Oktober 2000
  • Laatst online: 26-05 15:19

chem

Reist de wereld rond

Topicstarter
Ik heb het nu ff met een vrijwel geheel gelijkende methode als van drm gedaan.
Dit moet maar ff voldoen tot nu, later moet ik toch gewoon de zooi als array in de source hebben staan.

Klaar voor een nieuwe uitdaging.


  • Kwai_gon_jinn
  • Registratie: Januari 2001
  • Niet online

Kwai_gon_jinn

[-geen icon-]

PHP:
1
2
strpos( $string, "(" );
strrpos( $string, ")" );


aanvulling op de splitter? :)
Heb toch liever de RegExp.

Confucius said: "In ancient time, learning was for self. Nowadays learning is for others."

Pagina: 1