| 

.NET C# Java Javascript Exception

5
Hallo Leute,

ich bin leider nicht so wirklich fit mit dem Erstellen von RegEx-Pattern, darum könnte ich etwas Hilfe bei der Lösung folgenden Problems gebrauchen:
Ich möchte eine Zeichenkette so vereinfachen, dass am Ende nur noch Buchstaben, Ziffern und optional als erstes und/oder letztes Zeichen ein * steht.
Und es sollen mehrfach aufeinanderfolgende Buchstaben auf einen reduziert werden.
Beispiel:
*grassi-47tes soll ergeben *grasi47tes
wasssser*ball 58luft* soll ergeben waserbal58luft*

Wie sieht dafür das RegEx-Pattern aus?

Vielen Dank für Eure Hilfe
Carsten
News:
03.05.2012
Carsten Ilwig 337 1 1 6
2 Antworten
4
Um alles außer bestimmte Zeichen zu matchen, kannst du eine Zeichenklasse mit ^ invertieren. So matcht [^123] zum Beispiel alles, was keine 1, 2 oder 3 ist. Wenn du also jedes vorkommen von [^a-zA-Z0-9*] durch den leeren String ersetzt, wird alles weg geätzt was keine Ziffer, kein Buchstabe und kein Stern ist.

Um alle Sterne zu entfernen, die nicht am Anfang oder Ende auftauchen, kannst du jedes vorkommen von (.)\*(.) durch \1\2 ersetzen (sprich "beliebiges Zeichen, Stern, beliebiges Zeichen" wird zu "erstes beliebige Zeichen gefolgt von zweites beliebige Zeichen").

Um Buchstaben zu finden, die sich wiederholen, kannst du Backreferences verwenden, wenn deine Regex-Engine dieses Feature unterstützt. Der Regex dafür wäre "([a-zA-Z])\1+". Das kannst du dann durch \1 (i.e. der Buchstabe, der sich wiederholt) ersetzen und fertig.

Je nach Regex-Dialekt musst du statt \1 und \2 vielleicht auch $1 und $2 o.ä. schreiben.
03.05.2012
sepp2k 116 2
Vielen Dank für Deine schnelle Antwort.
Das hört sich auch alles prima an, nur leider habe ich keien Ahnung, wie ich nun aus dem Beschriebenen einen für mich verwendbaren RegEx zusammenbaue.
Ich habe es so versucht: ([a-z0-9*\1\2])\1
Da kam aber bei diesem Beispieltext *wasser&*bett*
nur das raus: sstt

Als RegEx-Engine verwende ich die vom .NET Framwork 4.0 mit C#.
– Gast 04.05.2012
Sorry, ich war noch nicht angemeldet.
Carsten Ilwig 04.05.2012
[^a-z0-9]

macht aus "*wasser&*bett*" -> "wasserbett"

string resultString = Regex.Replace(sourceString, "[^a-z0-9]", "", RegexOptions.IgnoreCase);
Floyd 04.05.2012
@Carsten Versuch doch einfach mal, jeden von mir beschriebenen Schritt einzeln zu implementieren. Es gibt keinen Grund, das alles in einen Ausdruck zu quetschen.
sepp2k 04.05.2012
1
Sehr hilfreich finde ich immer ein Tool mit dem man direkt testen kann, z.B. den Regex Designer (http://www.radsoftware.com.au/regexdesigner/) oder online http://regexpal.com/ ..
puls200 04.05.2012
2
Und für die richtig üblen Ausdrücke hilft der Debugger von RegexBuddy (http://www.regexbuddy.com/).
Die bieten auch ein Tool namens RegexMagic (http://www.regexmagic.com/), mit dem man reguläre Ausdrücke über ein GUI zusammenbauen kann ohne sich mit der Syntax zu beschäftigen (hab ich noch nicht ausprobiert, aber vlt. hilfts ja weiter)
ffordermaier 04.05.2012
1
RegexBuddy find ich sehr gut.
RegexMagic hab ich mal ausprobiert, bin aber überhaupt nicht damit klar gekommen.
Floyd 04.05.2012
2
Also vielen Dank erstmal an alle, für die Antworten.
Die vorgeschlagenen Tools mögen ja für jemanden, der sich bereits mit dem RegEx-Dialekt gut auskennt hilfreich sein, aber mir haben sie leider nicht geholfen.
Zu RegexBudy kann allerdings nichts sagen, da es dass nicht als Demoversion gibt.
Für RegexMagic muss wahrscheinlich erst eine Bedinerschulung absolvieren, sonst versteht man die sicherlich umfangreiche Funktionalität gar nicht erst, zumindest nicht für jemanden OHNE Regex Wissen.
Mit den beiden anderen Tools konn nmann wohl auch "nur" bereits vorhanden Regexpattern testen,
aber dazu muss man diese natürlich auch erst einmal haben.
Und da bin ich wieder bei meinem anfänglichen Problem.

@sepp2k:
Ich habe jetzt mal versucht in 3 Schritten zu meinem gewünschten Ergebnis zu kommen, aber leider ohne nennswerten Erfolg.
Das einzige was ich per RegEx hinbekomme, ist, dass mir aus meien Ausgangszeichenkette alle die Zeichen entfernt werden, die ich nicht haben möchte.
Das ist aber auch nicht wirklich schwierig. Dann komme ich nicht mehr weiter.
Ausgangsstring: *wasser&*bett*
1. Schritt: alle unerwünschten Zeichen entfernen:
Regex = [*a-zA-Z0-9] --> Ergeniss: *wasser*bett*

2. Schritt: Alle * die nicht am Anfang/Ende stehen entfernen: Quelle: *wasser*bett*
Regex = ((.)\*(.))\1\2 --> Ergeniss leere Zeichenkette

3. Schritt: doppelte Buchstaben entfernen: Quelle: *wasser*bett*
Regex = ([a-z])\1 --> Ergebnis sstt (leider genau verkehrtherum)

Mag sein, das ich mch beim Zusammenbauen der Regexe total ungeschickt anstelle,
nur leider habe ich keinen blassen Schimmer, wie die korrekte Syntax ist.
04.05.2012
Carsten Ilwig 337 1 1 6
Ich glaube du hast nicht ganz verstanden, was du mit den regulären Ausdrücken machen sollst. Bei Schritt drei kriegst du genau das verkehrte, weil du das Gegenteil machst, von dem was ich gesagt habe. Ich habe gesagt, du sollst alle vorkommen des Ausdrucks durch den leeren String ersetzen (d.h. löschen). Wenn du das machst kriegst du den String, den du willst. Bei 2 ist es ähnlich. Das \1\2 ist nicht Teil des Ausdrucks - das ist das, womit du den Ausdruck ersetzen sollst.
sepp2k 04.05.2012
Vielen Dank für Deine Geduld.
Aber genau das ist ja mein Problem, dass ich bisher nicht wirklich verstehe, was ich mit den Ausdrücken machen soll.
>du sollst alle vorkommen des Ausdrucks durch den leeren String ersetzen
Der Tip ist ja gut, nur ich habe keine Ahnung wie ich das mache. Genau deshalb habe ich ja angefragt.
Wie muss dafür der korrekte RegEx-Ausdruck aussehen?

Genauso, wenn Du schreibst:
>Das kannst du dann durch \1 ersetzen und fertig.
Das ist ja schön, nur was muss ich bei diesem Ausdruck "([a-zA-Z])\1+" durch \1 ersetzen??
Carsten Ilwig 04.05.2012
Es hat nichts damit zu tun, wie der Ausdruck aussieht. Der Ausdruck für 3. sieht schon richtig aus - da musst du nichts dran ändern (außer wenn du auch Großbuchstaben vereinfachen willst). Wie ich bereits sagte, ist das Problem nicht der Ausdruck, sondern was du damit machst. Um in C# Reguläre Ausdrücke zu ersetzen, benutzt man die Replace-Methode.
sepp2k 04.05.2012
Jaaa, jetzt habe ich es verstanden (zumindest den 3. Schritt). :-)
Meine Lösung in C# sieht nun wie folgt aus:
string returnValue = new Regex(@"([a-z])\1").Replace("*wasser*bett*", new MatchEvaluator(delegate(Match match) { return match.Value[0].ToString(); })); --> Ergenis: "*waser*bet*"

Jetzt bleibt nur noch das Problem mit den *, die nicht am Anfang, oder Ende stehen (Schritt 2).
>kannst du jedes vorkommen von (.)\*(.) durch \1\2 ersetzen
Hast Du dafür vielleicht auch noch mal einen Tip, wie Du das meinst?
Carsten Ilwig 04.05.2012
Alles was ich meinte war, Regex.Replace(string, @"(.)\*(.)", "$1$2"). Und für 3. reicht Regex.Replace(string, @"([a-z])\1", "$1") - da brauchst du keinen delegate.
sepp2k 04.05.2012
Programmierung kann doch soooo einfach sein, wenn man weiß wie es geht. ;-)
Vieeelen Dank an Dich für Deine Hilfe.
Jetzt ist das Wochenende gerettet.

Aber einen Vorteil hatte das Ganze hin und her doch, jetzt habe ich die Reg(H)Exerei (hoffentlich) etwas besser verstanden, als wenn Du mir die fertige Lösung sofort gepostet hättest.

Ich wünsche Dir ein erholsames Wochenende.
Carsten Ilwig 04.05.2012

Stelle deine Regex-Frage jetzt!