Laden...

Regex: Überspringen einer führenden Zeichenkette (rein per Regex-Pattern)

Erstellt von Maruu vor 12 Jahren Letzter Beitrag vor 12 Jahren 9.605 Views
M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren
Regex: Überspringen einer führenden Zeichenkette (rein per Regex-Pattern)

Hallo zusammen,

vorab, ich suche eine Lösung in Regex, das ich das ganze auch mit C# locker lösen kann ist mir klar. Leider steht mir an der Stelle nur Regex zur Verfügung.

Hier mein Problem, ich hab verschiedene strings die folgendermaßen aussehen können

12345
FBA-12345
FBA-FBA-12345
FBA-FBA-FBA-12345
FBA-F-12345

Man sieht das am Anfang die Zeichenkette "FBA-" beliebig oft (0 bis x mal) vorkommt. Ich benötige nun per Regex alles das hinter den "FBA-" Zeichenketten steht, also 12345 oder F-12345 (wie im letzten Beispiel).

Nun dachte ich das ich das ganze mit Lookarounds lösen kann z.B. (?≤FBA-).* habe aber irgendwo gelesen das man bei einem Lookaround nicht sagen kann das er beliebig oft vorkommen soll. Leider kann man anscheinend auch nicht ganze Zeichenketten sondern nur einzelne Buchstabe ausschließen. Daher weiß ich leider nicht mehr weiter, habt Ihr ne Idee oder geht das von mir gezeigt Beispiel nicht?

Gruß

Hannes

A
764 Beiträge seit 2007
vor 12 Jahren

[FBA-]*(?<DerHintereTeil>12345)

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

Hi,

das Problem ist das der hintere Teil variabel ist. Ich geb mal noch ein paar Beispiele:

FBA-45678
FBA-FBA-ABC12345
ABCDE

Hier soll dann 45678, ABC12345 und ABCDE erkannt werden. Es soll also lediglich das FBA- am Anfang weggeschnitten werden.

Gruß

Hannes

795 Beiträge seit 2006
vor 12 Jahren

Wie wäre es mit ^(FBA-)*(?<Anderes>.*)$

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
A
764 Beiträge seit 2007
vor 12 Jahren

Ich empfehle dir mal die Lektüre von: [Artikel] Regex-Tutorial. Ausserdem ist das RegEx Studio ausgesprochen hilfreich.

Deine Fragen fallen übrigens unter: [Hinweis] Wie poste ich richtig? Punkt 1.1 und 1.1.1

Noch als Hinweis für Ausdrücke ohne FBA-: einen eingeklammerten bereich kannst du mit ? optional machen:( ((FBA-)*)?

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

@TheBrainiac: Danke, aber was steht denn anstelle von <Anderes> ? Irgendwie steh ich da auf dem Schlauch.

@ Alf Ator: die Tutorials habe ich gelesen und auch schon einiges ausprobiert. Ich hatte schon einige Regex gebastelt aber an dieser Stelle komm ich einfach nicht weiter. Hab mir auch schon RegEx Studio installiert, aber das macht leide rauch nicht allzuviel mehr wie z.B. http://regexp-tester.mediacix.de/exp/regex/. Leider hab ich auch in der Suche nix passendes zu dem gleichen Problem gefunden, daher mein Post.

Das Problem bei ^(FBA-)(?<Anderes>.)$ oder ((FBA-)*)? scheint mir das ich immer das FBA noch als Matching mitbekomme. Irgendwie steh ich da auf dem Schlauch, ich brauch doch eigentlich einen gierigen Ausdruck der den Anfang mit FBA- entfallen lässt.

R
100 Beiträge seit 2009
vor 12 Jahren

@Maruu: Probier mal mit dem


			Regex regex = new Regex("^(FBA-)*(.*)$");

			foreach (string temp in @"12345
FBA-12345
FBA-FBA-12345
FBA-FBA-FBA-12345
FBA-F-12345
FBA-45678
FBA-FBA-ABC12345
ABCDE".Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
			{
				foreach (Match match in regex.Matches(temp))
				{
					Console.WriteLine(match.Groups[match.Groups.Count - 1].Value.ToString());
				}
			}

			Console.ReadLine();

Edited: Regex verbessern damit Empty-String nicht in Matches steht

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

Hallo rongchaua,

Du hast schon recht, die von Dir gezeigte Methode funtkioniert aber leider kann ich den C# Code vor oder nach dem RegEx nicht beinflussne, ich kann also nicht sagen das er die erste oder letzte Gruppe des Matchings nehmen soll. Das gesucht RegEx dürfte nur ein Ergebnis haben.

Gruß

Hannes

A
764 Beiträge seit 2007
vor 12 Jahren

Das wird so nicht funktionieren.

A
764 Beiträge seit 2007
vor 12 Jahren

Probiers doch mal so aus:

[FBA-].*

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

Hi Alf Ator,

sowas in die Richtung hatte ich auch schon, leider muss er auch folgendes erkennen:

FBA-FBA-F-12345

also F-12345

er soll also wirklich nur FBA- wegschneiden und kein einzelnes F-

Gruß

Hannes

795 Beiträge seit 2006
vor 12 Jahren

Meines ist doch schon richtig, so wie ich dich verstanden habe.

Mache einfach ein Match auf ^(FBA-)*(?<Anderes>.*)$.

Dann kannst du über myMatch.Groups["Anderes"].Value auf den Rest des Matches zugreifen...

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
A
764 Beiträge seit 2007
vor 12 Jahren

@TheBrainiac: Das geht leider nicht, weil er nur zugriff auf den RegexPattern hat.

@Maruu: Nachdem ich dein Problem verstanden habe, ich glaube das ist mit Regex nicht möglich. Du wirst da wohl eine andere Möglichkeit finden müssen.

S
417 Beiträge seit 2008
vor 12 Jahren

Hallo,

mach es so, und es wird klappen:

(?:FBA-)*(.+)
49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Sarc,

nein, auch der Pattern tuts nicht, denn bei dem sind die "FBA-" ja Teil des Matches. Und Maruu hat eben keinen Zugriff auf einzelne Gruppen.

Hallo Maruu,

obwohl das Forum kein Patterngenerator ist, will ich in dem Fall mal eine Ausnahme machen, um das Trauerspiel in diesem Thread zu beenden. Folgender Pattern tuts, vorausgesetzt, du willst den Teil hinter dem letzten "FBA-".

.((?<!FBA-).)*$

herbivore

PS: Alternativ formuliert: (.(?<!FBA-))+$

C
252 Beiträge seit 2007
vor 12 Jahren

Muss es denn unbedingt Regex sein? Ich bin jetzt auch nicht so der Regex Profi, aber wenn ich nicht auf das betreffende Pattern komme dann müssen eben mal die String-Operationen herhalten.
Also in deinem Bsp dann so:


      const string searchPattern = "FBA-";
      string[] toSearch = {"12345", "FBA-12345", "FBA-FBA-12345", "FBA-FBA-FBA-12345", "FBA-F-12345"};

      foreach (var s in toSearch)
      {        
        int index = s.LastIndexOf(searchPattern, StringComparison.Ordinal);
        string result = index == -1 ? s : s.Substring(index + searchPattern.Length);
        Console.WriteLine(result);
      }

Hinweis von herbivore vor 12 Jahren

Muss es denn unbedingt Regex sein?

Wer lesen kann ist klar im Vorteil:

vorab, ich suche eine Lösung in Regex, das ich das ganze auch mit C# locker lösen kann ist mir klar. Leider steht mir an der Stelle nur Regex zur Verfügung.

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

Hallo alle zusammen,

vielen Dank für die vielen Antworten. Ich will das Forum wirklich nichta ls RegEx generator missbrauchen, das ganze ist nur sehr kompliziert, das hat man an den vielen Antworten gesehen. Ich hab bereits schon einiges mit RegEx gemacht nur da bin ich leide rnicht drauf gekommen.

Vielen vielen Dank an herbivore, das war die richtige Lösung:

.((?<!FBA-).)*$

das ist das Statement da funktioniert!

Auch vielen Dank an alle Anderen für die Hilfe.

Gruß

Hannes

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

Hallo herbivore,

sorry, ich muss doch nochmal nachhaken. Das RegEx-Statement funktioniert super aber ich will es gerne auch verstehen damit ich es nächstes mal auch selbst anwenden kann.

Hier nochmal das Statement:

.((?<!FBA-).)*$

Ich nehm es jetzt mal auseinander:

(?<!FBA-) macht ja nichts anderes als zu sagen es darf vor dem gesuchten String kein FBA- vorkommen.

Ich vermute da man das Statement nicht beliebig oft machen kann, also (?<!FBA-)* geht nicht, hast Du den Punkt und die Klammern drum rum danach angefügt um das nächste Zeichen optional noch mitzunehmen also ((?<!FBA-).) und das ganze Statement kann man nun optional und beliebig oft machen mit ((?<!FBA-).)*

So da es ja ein negatives Lookaround ist durchsuchen wir die Zeichenkette von hinten daher das $

Und da das Statement ((?<!FBA-).)* von einem String FBA-12345 nicht nur FBA- abschneidet sondern auch das erste Folgezeichen, also FBA-1 abschneidet, muss dieses erste Folgezeichen doch wieder mitgenommen werden, daher noch der führende Punkt im .((?<!FBA-).)*$

Lieg ich da grob richtig?

Gruß

Hannes

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Maruu,

ich hatte in meinem Beitrag oben später noch eine alternative Formulierung des Pattern angegeben, die noch einen Tick eleganter und vielleicht auch klarer ist: (.(?<!FBA-))+$ Deshalb nehme ich in meiner Erklärung auch diese Alternative als Basis.

(?<!FBA-) macht ja nichts anderes als zu sagen es darf vor dem gesuchten String kein FBA- vorkommen.

Fast, (?<!FBA-) macht nichts anderes als zu sagen, es darf vor der aktuellen Position kein FBA- vorkommen. Und was auch noch wichtig ist zu wissen: Ein Lookaround hat im Ergebnis immer die Länge 0, egal wielang die Zeichenfolge ist, auf die er passt (bzw. nicht passt). Er sagt also nur, die Bedingung ist an dieser Position erfüllt oder eben nicht erfüllt, je nachdem was zutrifft. Er frisst keine Zeichen.

Ich vermute da man das Statement nicht beliebig oft machen kann, also (?<!FBA-)* geht nicht

Das Problem mit dem Stern ist, dass dadurch das Statement, auf das er sich bezieht, gar nicht vorkommen muss. Das ist natürlich nicht, was man will. Zu sagen an dieser Position muss ein Lookaround erfüllt sein oder nicht erfüllt sein, ist Unsinn. Denn das ist im Ergebnis immer wahr.

Aber selbst wenn man (?<!FBA-)+ verwenden würde, dann würde sich das ja immer noch auf die aktuelle Position beziehen. Und wenn die Bedingung einmal erfüllt ist, dann ist sie auch 10 mal erfüllt. Denn ein Lookahead frisst wie gesagt keine Zeichen. Auch bei 10maliger Wiederholung wird immer noch an der gleichen Position geprüft. Wenn die Bedingung nicht erfüllt ist, wird sie auch bei 10maliger Wiederholung nicht erfüllt. Ein Wiederholungszeichen (Quantor) hinter einem Lookahead ist also so oder so Unsinn.

hast Du den Punkt und die Klammern drum rum danach angefügt um das nächste Zeichen optional noch mitzunehmen also ((?<!FBA-).) und das ganze Statement kann man nun optional und beliebig oft machen mit ((?<!FBA-).)*

Ich würde das anders formulieren. Ich habe den Punkt verwendet, weil ich ja auf beliebigen Text matchen will. Nämlich auf alles, was hinter dem letzten FBA- steht, egal was das ist.

Wenn ich die Bedingung "nur hinter dem letzten FBA-" mal weglasse, dann sieht der Pattern so aus: (.)+$ oder einfach nur .+$ weil die Klammern dann ja nicht benötigt werden.

Jetzt kann ich den Spieß wieder umdrehen und mich fragen, wie ich diesen Pattern so erweitern kann, dass die Bedingung, dass der Pattern nur auf den Teil hinter dem letzten FBA- passen soll, erfüllt wird. Dazu kann ich die Bedingung auch anders formulieren: Innerhalb des gesuchten Texts darf an keiner Stelle ein FBA- auftauchen. Das bedeutet, ich muss prüfen, dass sich dort an jeder Position kein FBA- befindet. Und genau das tut der negative Lookbehind.

Also wird aus (.)*$ wieder (.(?<!FBA-))+$

So da es ja ein negatives Lookaround ist durchsuchen wir die Zeichenkette von hinten daher das $

Nee, Regex matcht immer von links nach rechts. In welche Richtung die Lookarounds arbeiten, spielt dafür keine Rolle.

Du kannst ja mal im On-the-fly Regex-Tester: Regex-Lab das $ weglassen (Input z.B. FBA-12345). Dann siehst du, wozu es da ist.

daher noch der führende Punkt im .((?<!FBA-).)*$

Der zusätzliche Punkt ist in der alternativen Formulierung nicht mehr nötig. Im Grunde ging es nur darum, dass die Lookbehind-Bedingung nur zwischen den Punkten geprüft werden muss, nicht vor dem ersten Punkt. Sonst würde das erste Zeichen hinter dem FBA- unterschlagen werden.

herbivore

M
Maruu Themenstarter:in
121 Beiträge seit 2006
vor 12 Jahren

Besten Dank, langsam wird es hell 😃 Trivial war dieses Statement dennoch nicht.

Gruß

Hannes