Laden...

Hilfe mit schwierigem Regex

Erstellt von jofenchel vor 18 Jahren Letzter Beitrag vor 18 Jahren 3.278 Views
jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren
Hilfe mit schwierigem Regex

Hallo zusammen,
ich sollte bitte ein wenig Hilfe mit einem sehr schwierigen Regex haben.

Hier der String:
[php]string s = "6008970: #IP4 CALLs S_AGW_LAUTSTAERKE6008970: (S:LEISE)";[/php]

Ich wuerde gerne, falls machbar, die folgenden Infos aus dem String ziehen:

S_AGW_LAUTSTAERKE(S:LEISE)
Manchmal sind die Klammern "(LEISE)" auch leer "()".

Das Problem ist das die nummerischen Zeichen dazwischen liegen.

Folgenden RegEx habe ich mal gebastelt:

Regex check  = new Regex( String.Format("Calls S_{0}_(.+?)", ecu),RegexOptions.IgnoreCase );

Die Variabel vom string ecu fuetter ich mit args[0].
In diesem Beispiel hat args[0] dann "AGW".

Vielen Dank fuer Hilfe.

JoFenchel

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo jofenchel,

"schwierig" ist hier wohl eine Frage des Betrachters. 🙂

Es geht doch wieder (frei) nach dem Schema wie in Negierte Zeichen beschrieben.

Also erstmal den Zielstring:

@"S_AGW_LAUTSTAERKE6008970: (S:LEISE)"

Dann die Zeichen quoten, die in Regex eine Sonderbedeutung haben:

@"S_AGW_LAUTSTAERKE6008970: (S:LEISE)"

Dann die Teile, die variabel sein sollen:

@"S_AGW_LAUTSTAERKE\d*: ([^)]*)"

Den Teil mit dem AWG hast du ja schon, nur dass du sicherheitshabler Regex.Escape (ecu) verwenden solltest.

herbivore

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

hallo herbivore,

klappt nicht so richtig.
ich denke auch das du mich falsch verstanden hast. oder ich habe mich nicht richtig ausgedrueckt.
ich habe folgende strings:


5551590: #IP3 CALLs S_AGW_INIT5551590: ()
5588840: #IP9 CALLs S_AGW_FLOE5588840: ()
6008970: #IP4 CALLs S_AGW_LAUTSTAERKE6008970: (S:LEISE)
6244970: #IP11 CALLs S_AGW_FLES6244970: ()
6249670: #IP3 CALLs S_AGW_ENDE6249670: ()

Als Parameter gebe ich den AGW in der Eingabeauforderung mit.
Manche strings enden mit "(S:LEISE)" oder nur mit "()".
Nun muss ich alle S_AGW* herausfiltern.
Am Ende habe ich das Problem das nummerische Zeichen vor dem "(S:LEISE)" oder dem "()" stehen.

Am Ende moechte ich in einem Array folgende gefundene Treffer speichern:


S_AGW_INIT5()                  
S_AGW_FLOE()                   
S_AGW_LAUTSTAERKE(S:LEISE)     
S_AGW_FLES()                   
S_AGW_ENDE()                   

Somit kann ich dann spaeter alle SEQ zu dem entprechenden Steuergeraet suchen.
Gruss
JoFenchel

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo jofenchel,

habe ich in der Tat nicht so verstanden, aber das ist auch nicht schwer:

@"(?<name>S_AGW_[A-Z]+)\d*: (?<param>((S:LEISE)?))"

Wenn du nachher eine Match m hast, dann ist das was du willst:

m.Groups["name"] + m.Groups["param"]

herbivore

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Hallo Herbivore,

sorry, aber ich verstehe nur Bahnhof 🙂)

Harter Tobak.

JoFenchel

I
1.739 Beiträge seit 2005
vor 18 Jahren

"sorry, aber ich verstehe nur Bahnhof 🙂)

Harter Tobak."

In der Tat, Regular Expressions sind ein Thema für sich. Zum Glück standardisiert(also nicht für jede Programmiersprache oder sonst. Anwendung anders).
Ich denke ohne hinzuschauen kannst du herbivors Bsp. einfach übernehmen. Ansonsten zum Einstieg in Wikipedia nachschauen. Oder von O'Reilly(Verlag) gibts ein gutes Buch das mit rund 500 Seiten einen Einstieg vermittelt 😉...

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

hallo ikaros,

danke fuer den tip.
Ja, der Vorschlag von herbivore funktioniert echt Klasse.

Ich verstehe schon C# und die syntax nach ein wnig ueben.
aber das mit regex da hab ich wirklich probleme mit.
gebe ich echt zu, tue mich da echt schwer.
trotz buch.

bleibe am ball.

JoFenchel

I
1.739 Beiträge seit 2005
vor 18 Jahren

Mein Tipp: nicht aufgeben, irgendwann machts klick und alles wird simpel...
Bist auf dem richtigen Weg! Bücher brauch man dann irgendwann nur als Referenz(wer will Lexikon sein wenn er denken kann 😉 )... Oder zum Einstieg zu neuen Techn.

563 Beiträge seit 2004
vor 18 Jahren

regex sind kompliziert, wenn man sich nie damit beschäftigt hat. arbeitet man öfters mit regex, merkt man, wie einfach es eigentlich ist, und trotzdem brutal effektiv! (meine Erfahrung).

die regex sehen immer so kompliziert aus, sind sie aber definitiv nicht 😉 ich finde herbivores arbeitsmethode, einen regex zu schreiben, sehr gut! sowas liest man nicht unbedingt auf msdn.microsoft.com 😉

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Hallo unreal,

stimmt.
Seine Methode ist sehr gut. Da gibt es keinen Zweifel.
Bin Ihm auch echt dankbar.

Aber ich habe halt Probleme RegEx zu kapieren.

JoFenchel

S
709 Beiträge seit 2005
vor 18 Jahren

Noch was ganz nützliches: Reguläre Ausdrücke in C#

Da wird auch erklärt, wie das ganze mit C# funktioniert.
Gruß,
SimonKnight6600

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Danke SimonKnight6600 fuer den Link.

Ist wirklcih sehr gut erklaert.

Gruss
JoFenchel

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Hallo Herbivore,

ich habe es soweit hinbekommen.
Nur!!!
Wenn ich so einen STring habe klappt es nicht:

"6256990: #IP0 CALLs S_ZGW211_MONTAGEBIT_SCHREIBEN6256990: (i_bit_position:I:3,I:0)",

Ich habe es mit dem RegEx probiert komme aber nicht zum Erfolg:

@"(?<name>S_{0}_[A-Z]+)\d*: (?<param>\(([A-z,0-9])?\))"

Irgendwie passt der hintere Teil noch nicht ganz.

Gruss
JoFenchel

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo jofenchel,

wenn ich Regex nicht könnte, wäre das ein typischer Fall, bei dem ich mich so lange durch die Doku wühlen würde, bis ich selbst hinbekommen hätte, weil mir klar wäre, dass das was sehr überschaubares sein muss. Es ist zwar im ersten Moment aufwändiger als im Forum zu fragen, aber wenn man öfter mit Regex arbeiten will oder muss, ist der Lernerfolg wichtiger als der Zeitaufwand. Und ich meine wirklich Doku lesen und nicht nur verschiedene Varianten probieren.

Irgendwie passt der hintere Teil noch nicht ganz.

Der vordere Teil passt auch noch nicht ganz. 🙂

Wenn du es wirklich nicht hinbekommst, bin ich der letzte, der dich hängen lässt, aber ich denke du musst auch auf eigenen Regex-Füßen stehen.

herbivore

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Hallo Herbivore,

ich denke ich habe es:

Regex check  = new Regex( String.Format( @"(?<name>S_{0}_[A-Z].+?)\d*: (?<param>\((.+?)?\))", ecu),RegexOptions.IgnoreCase );

Da ich an allen Zeichen in den Klammern interessiert bin kommt es mir auf das "S:LEISE" nicht an.
Denn manche Klammern koennen auch leer sein.

Mit diesem Regex finde ich alle.
In der string variablen "ecu" speichere ich den Namen des Steuergeraetes.
Eventuell ist es nicht die eleganteste Loesung mit .+? aber es klappt.

JoFenchel

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo jofenchel,

fein!

Ich versuche .*? in der Tat zu vermeiden, weil es manchmal nicht das tut, was man will.

Besser wäre vielleicht [^)]* also bel. viele "Nicht-Klammer-zu-Zeichen".

Ich denke, du müsstest auch noch das [A-Z] in [A-Z_] ändern.

herbivore

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Hallo Herbivore,

Ich denke, du müsstest auch noch das [A-Z] in [A-Z_] ändern.

es wird aber auch der String gefunden:

"6256990: #IP0 CALLs S_ZGW211_MONTAGEBIT_SCHREIBEN6256990: (i_bit_position:I:3,I:0)",

Aber ich habe noch ein anderes Problem:

"6244970: #IP11 CALLs S_AGW_FLES",

Der wird nicht gefunden.
Weil es keine Klammern gibt. Kann auch vorkommen.
Aber lass mich nochmal tuefteln.
Was dein RegEx macht habe ich soweit begriffen. Er speichert gefudene Zeichenfolgen in Gruppennamen ab.
Muss nur noch einen Weg finden um auch solche zu finden wo keine Klammern am Ende vorkommen.

Gruss
JoFenchel

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Sorry Herbivore,

ich weis nicht wie da ein ODER einbauen soll das der RegExe auch Strings akzeptiert die keine "()" haben.

@"(?<name>S_{0}_[A-Z_]+)\d*: (?<param>\((.+?)?\))", ecu

Ich muss da noch ein ODER einbauen sodas der RegEx auch Strings ohne Klammern akzeptiert.

Ich denke das das ODER hier zwischen muss:

\d*: 

Gruss
JoFenchel

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo jofenchel,

so Sachen stehen doch in der Doku: (a|b)

Aber hier würde ich es einfach per Fragezeichen optional machen:

@"(?<name>S_{0}[A-Z]+)\d*(: (?<param>([^)]*)))?"

herbivore

jofenchel Themenstarter:in
117 Beiträge seit 2005
vor 18 Jahren

Hallo Herbivore,

so Sachen stehen doch in der Doku: (a|b)

das habe ich gewusst.
Aber wo ist die ODER in diesem RegEx?

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo jofenchel,

hier geht es ja um alles oder nichts 🙂 Das wäre ein merkwürdiges Konstrukt in Regex:

(alles|)

Also ein Oder, bei dem ein Teil leer bleibt. Dafür nimmt man besser das Fragezeichen, wodurch der eingeklammerte Teil optional wird:

(alles)?

und was ich auch verwendet habe. Wenn du wirklich ein Oder willst, dann musst du in meinem Pattern )? durch |) ersetzen. Thats all.

herbivore