2009-08-27 4 views
0

Die Sprache Ruby, hier ist meine irb SitzungWarum verkettet sich der letzte Ausdruck in meinem regulären Ausdruck mit dem ersten?

expr = /\Aselect from (\D+)(?: (?:where|&&) (\D+) (\S+) (\S+))*(?: order by (\D+) (asc|desc))?\Z/ 
=> /\Aselect from (\D+)(?: (?:where|&&) (\D+) (\S+) (\S+))*(?: order by (\D+) (asc|desc))?\Z/ 

/> str = "select from Entity order by value desc" 
=> "select from Entity order by value desc" 

/> expr =~ str 
=> 0 

/> $1 
=> "Entity order by value desc" 

/> $2 
=> nil 

Ich verstehe einfach nicht, warum ich „Entity, um von Wert ab“ $ 1 bin immer. Das gewünschte Verhalten wäre hier $ 1 => "Entity", $ 2 => "value", $ 3 => "desc". Was mache ich falsch? Wie ändere ich diesen regulären Ausdruck, damit ich diese Ergebnisse erhalte?

Danke

Antwort

4

\ D ist „nicht digit“, die die Leerzeichen zwischen den Wörtern umfasst, sowie die folgenden Worte. Versuchen Sie stattdessen (\ S +).

[Bearbeiten] Sorry, ich habe die Frage am Ende verpasst. Das Obige beantwortet die Frage "Warum passiert das?", Aber nicht "Wie erreiche ich, was ich wollte?". Hier ist eine Art und Weise ist, alle anderen Klauseln mit einer Umgehung. *

/\Aselect from (\S+).*(?:order by (\S+) (asc|desc)?)?\Z/ 

Da SQL ziemlich frei ist mit Abstand und so zwischen Keywords, die Dir vielleicht gefallen es mehr lesbar zu machen und verwenden \ + statt wörtliche Räume s. Das heißt, der Ausdruck als Service-Leistung nicht überein:

"select from  Fred" 

aber es wäre, wenn Sie did/\ AWählen \ s + von \ s + ....

1

Die (\D+) ist gierig und hat gegessen der Rest der Zeichenfolge. Da alles andere in Ihrem Ausdruck optional ist (* oder?), Müssen Sie ihn nicht zuordnen, damit der Ausdruck erfolgreich ist.

Mein Vorschlag ist es, Ihre Spiele weniger gierig zu machen. ZB (\D+?) wird übereinstimmen und erfassen alle nicht-Ziffer ein oder mehrere Male, aber so oft wie nötig, um eine erfolgreiche Übereinstimmung zu machen.