2010-12-22 5 views
1

Zunächst einmal möchte ich nur sagen, dass ich noch nie so gut die regulären Ausdrücke Muster verstanden, aber ich bin voran :)regex für pow()

ich eine Funktion zum Ersetzen der „^“ erstellen möchten char und left right passt zu pow ($ 1, $ 2). Ich manged an einen Punkt zu gelangen, die akzeptabel ist, aber die Zeichenfolge, die ich von einer API erhalten bleibt immer größer & größer und jetzt bin ich stecken ... es ist so:

$str = '(0+1*9^3+3)*(4+5)-(6/7)+(1+2)/(1+1)^((2/3)*3-1+(2/3))'; 
$str = preg_replace('/([0-9]+|\([0-9\+\-\*\/]+\)|[^\+\-\*\/]\([\S]+\))\^([0-9]+|\([0-9\+\-\*\/]+\)|[^\+\-\*\/]\([\S]+\))/', 'pow($1,$2)', $str); 
echo $str; 

Dies funktioniert ok auf den gegebenen string, aber wenn ich 1 mehr "+ (1 + 2)/(1 + 1)^((2/3) * 3-1 + (2/3)) '" am Ende hinzufüge, funktioniert es nicht richtig.

Grundsätzlich mag ich preg_replace das finden, zuerst „()“ von links & der ersten „()“ von rechts „^“ char

Beispielen, wie es funktionieren soll (ich nur tun würde für die linke Seite von „^“ aber es kann gilt auch auf der rechten Seite)

3+2^3-2 => 3+pow(2, 3)-2 
3+(1+1)^3*2 => 3+pow((1+1), 3)*2 
3+(1+1+(1+2))^3/2 => 3+pow((1+1+(1+2)), 3)/2 
3+((3/3)+(2/2))^2-1 => 3+pow(((3/3)+(2/2)), 2)-1 
(3+1)^3-1 => pow((3+1), 3)-1 

etc ...

Sortieren für alle oben ist: Rückkehr als „$ 1“, was vor "^": 1. wenn das erste vor"^"ist int, gebe die Nummer zurück 2. Wenn das erste Ding ist ")" Suche nach seinem Paar "(" und "" zurückgeben alles in ihnen (etwas wie '/(/([.*]))\^/')

Es tut mir leid für mein Englisch, ich hoffe, Sie verstanden ... und ich hoffe, dass mir jemand zu diesem Problem helfen kann :(

Vielen Dank im Voraus!

Antwort

3

Das Problem hier ist, dass Sie einen Parser benötigen. Unendlich verschachtelte Ausdrücke (wie in Klammern) können nicht nur durch reguläre Ausdrücke abgeglichen werden(). Stellen Sie sich Folgendes vor:

(2^(2^(2^(2^(2^(2^(...))))))) 

Welcher reguläre Ausdruck entspricht dem? Sie können es annähern, Sie können N Niveaus davon zusammenbringen, aber Sie können nicht alles tun.

Sie sollten machen einen Parser. Wenn Sie nicht wollen, verstehe ich, weil es eine Menge Arbeit ist. Möglicherweise können Sie jetzt eine Regex-Lösung erhalten, die für Ihre Zwecke gut genug ist. Aber es wird nicht für immer funktionieren, weil reguläre Ausdrücke nicht ausreichend fortgeschritten sind, um dieses Problem zu lösen.


  1. Perl (und Perl-kompatible reguläre Ausdrücke) kann dies tun, aber sie sollten nicht. Sobald Sie anfangen, diese Funktionen von Perls Regexes zu benutzen, wird es unlesbar. Auch sind sie nicht (theoretisch) regulären Ausdrücke, aber niemand kümmert sich wirklich um Theorie. : P