Laden...

RegEx pattern für Quellcode einer Methodendefinition

Erstellt von medi vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.344 Views
M
medi Themenstarter:in
126 Beiträge seit 2005
vor 14 Jahren
RegEx pattern für Quellcode einer Methodendefinition

Hallo,

momentan muss ich mich mit regulären Ausdrücken und RegEx beschäftigen und nachdem ich mir dieses tolle Tutorial gegeben habe, habe ich noch ein Problem und hoffe ihr könnt mir bei der Lösung helfen.

Ich habe also eine Datei mit folgenden Beispielzeilen (Codeausschnitt) Code die analysiert werden sollen:

define method .vesExcelFiller(!pathOfTemplate is STRING, !pathOfNew is STRING, !nameOfSheet is STRING)
define method .vesExcelFiller(!pathOfTemplate is STRING, !pathOfNew is STRING, !nameOfSheet is STRING, !pathOfGraphicFile is STRING)
define method .addUniqueAttributes(!names is ARRAY, !values is ARRAY)
define method .clearUniqueEntries() clearUniqueEntries

Nutze ich jetzt z.B. bei der ersten Methode diesen pattern:
** define method +.(\w)(?# method name)((?:!(\w*)(?# parameter name) +is +([A-Z])(?# parameter type)(?:, +)?(?:\r\n)?))**
dann extrahiert er mir nur folgende drei Parameter:
vesExcelFiller nameOfSheet STRING
Ihr seht das Problem ist, dass er mir nur einen parameter aus der methode holt - die anderen bekomme ich nicht zurück bzw. die werden überschrieben.
Gibt es eine Möglichkeit alle Parameter zurückgeben zu lassen ohne das ich nen ewig langen pattern konstruiere?

Hoffe auf Hilfe und bedanke mich schonmal 😉

R
164 Beiträge seit 2008
vor 14 Jahren

Regex braucht man für die einfachen Konstrukte eigentlich nicht, es reichen Operationen mit der string-Klasse. Jede Methode beginnt mit "define method.", also kann man diese Zeichenfolge suchen mit der string.IndexOf()-Methode. Dann addiert man zum Ergebnis der IndexOf-Methode die Länge der "define method."-Zeichenfolge, um den Anfang des Methodennamens zu erhalten. Danach splittet man den restlichen String nach "(" und ")" mit string.Split().
Man erhält dann die Teile:


[0] vesExcelFiller
[1] !pathOfTemplate is STRING, !pathOfNew is STRING, !nameOfSheet is STRING

Den String mit den Parametern splittet man nun nach den Kommas. Der Teil zwischen Ausrufungszeichen und Leerzeichen ist ein Parameter.

564 Beiträge seit 2005
vor 14 Jahren

Hol dir zuerst die Klammer und danach mit Regex.Matches die einzelnen Parameter.

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 14 Jahren

@rechner
Das Problem ist, dass dann das Programm wieder zu unflexibel wird. Die Pattern werden aus einem SettingFile ausgelesen und dann vom Programm umgesetzt und diese nutzt um dann die Ergbnisse weiter zu verarbeiten. Dieses Settingfile wird von Kunde zu Kunde (sollte es mal Kunden geben ausser uns selbst 😉 ) anders gefüllt da wohl die jeder Kunde einen anderen Dateiaufbau hat und das definieren der Methoden nicht ganz so star ist. Was ich damit sagen will: Das Beispiel da oben ist so wie wir es machen, andere können das anders machen deswegen die wohl von RegEx damit man flexibel ist. Trotzdem danke für deinen Kommentar.

@ZiMD
Hab dich nicht wirklich verstanden 👶
meinst du zwei schritte? also erst das
define method +.(\w)(((?:\S* +is +[A-Z]*(?: , )?))
und dann das nochmal
!(\w
) +is +([A-Z]+)(?: *, *)?

564 Beiträge seit 2005
vor 14 Jahren

Du hast mich verstanden 👅

Beim zweiten Regex aber die Matches-Methode verwenden.

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo medi,

Regex.Matches ist nicht nötig. Du kannst dir die einzelnen Parameter aus Match.Groups[].Captures[] holen.

Wo welches Ergebnis wo drinsteht, siehst du auch gut in On-the-fly Regex-Tester: Regex-Lab, wenn du die Haken bei Groups und Captures setzt.

herbivore

564 Beiträge seit 2005
vor 14 Jahren

Das kannte ich noch gar nicht. Hat das Vorteile gegenüber Matches?

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo ZiMD,

der Vorteil ist, dass man den Pattern nicht aufteilen muss.

herbivore

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 14 Jahren

So, danke für die Antowrten. Habs mitlerweile zum Fliegen gebracht.

und zwar so:

Regex myRegex = new Regex( pattern );

                Match match = myRegex.Match( this.fileContent );
                while ( match.Success ) {
                    for ( int i = 1; i < match.Groups.Count; i++ ) {
                        tmpResult.Add( value );
                    }
                    result.Add( tmpResult );
                    tmpResult = new List<string>();
                    match = match.NextMatch();
                }

Aber jetzt hab ich ein naderes Problem mit nem RegExp ansich, ich hoffe ihr könnt mir da helfen...finde da keine Lösung zu:

Ich bekomm folgendes Problem einfach nicht gebacken...habe hier den Inhalt einer Datei

$(---------------------------------------------------------------------------
-- Method:      .addColumn()
--
-- Description: adds a column to the current list ( fg.ds )
-- dsfs fs sjghk ( fg.ds )
-- ewrw erwe ff dfsf fsdfawe ( fg.ds )
--
-- Method Type: Procedure
--
-- Arguments:
--  [#] [R/RW] [Data Type] [Description]
--   1    R     ARRAY       column to add
-- Return:
--             [Data Type] [Description]
---------------------------------------------------------------------------$)

und will den Part hier


-- Description: adds a column to the current list ( fg.ds )
-- dsfs fs sjghk ( fg.ds )
-- ewrw erwe ff dfsf fsdfawe ( fg.ds )

mit einem regulären Ausdruck extrahieren...wie mach ich das? Hinzu zu fügen wäre noch, dass die Description Zeile 1 bis n-zeilig sein kann und es auch nicht zwingend eine "--" leerzeile vor "-- Method Type" geben muss aber kann.

mein bisheriger Ausdruck sah so aus:

-- +Description\: *((?:(?:\w* *\.*)*(?:\(|\))?)*(?:(?:\r\n--) *(?:(?:\w* *\.*)*(?:\(|\))?)*)*)

allerdings zieht er da vor allem die "-- Method Type" Zeile mit rein - was er unter gar keinem Fall machen soll. (scheinbar bricht er auch nur am : ab)

Mit lookahead komm ich nicht klar bzw. weiss ich nicht wo ich das am besten plazieren denn so:

-- +Description\: *((?:(?:\w* *\.*)*(?:\(|\))?)*(?:(?:\r\n--) *(?:(?:\w* *\.*)*(?:\(|\))?)*)*)(?=\r\n-- +Method)

gehts nicht 😭 (wieso auch immer...hab das lookahead wohl nicht richtig verstanden)

Bin grad böse am verzweifeln...

ne Idee?

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo medi,

sieht mir irgendwie unnötig kompliziert aus.

Was spricht gegen:

-- Description:(.(?!-- Method Type))* mit RegexOption.SingleLine

herbivore

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 14 Jahren
-- +Description\:((:question:\S| *)+\r\n)+(?=-- +Method Type:)

der hat jetzt funktioniert 🙂

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo medi,

mal abgesehen davon, dass dein Pattern durch den * nach dem Leerzeichen massives Backtracking auslösen kann und du deshalb den Stern unbedingt entfernen solltest, hat das Arbeiten mit einem positiven Lookahead statt eines negativen leider das Problem, dass mal u.U. über das Ziel hinausschießt. Dann bekommt man z.B. alles zwischen dem ersten "-- Description" und dem letzten "-- Method Type".

Ist außerdem sichergestellt, dass keine Tabs vorkommen können? Die würden nämlich einen Match verhindern.

herbivore

M
medi Themenstarter:in
126 Beiträge seit 2005
vor 14 Jahren

Durch was soll ich denn den * ersetzen wenn ich nicht genau weiss wie viele Leerzeichen folgen könnten? Durch eine Min-Max Angabe z.B. {0, 20}? Das Selbe trifft dann wohl auch für das + zu, oder?
Tabs können nicht auftreten, die werden durch Ultraedit beim Erzeugen der Dateien durch Leerzeichen ersetzt.

Ansonsten funktioniert deine Variante super. Danke für den Tipp!

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo medi,

den Stern kannst du einfach weglassen. Dahinter steht doch eh noch ein Plus (und weil das Plus dasteht gibt es ja auch überhaupt erst das Backtracking-Problem).

Das mit den Tabs würde ich noch einbauen. Irgendwer benutzt mal einen anderen Editor und schon gibt es ein Problem.

herbivore