2016-03-21 12 views
1

Ich habe diese Textzeile, die ich mit Regex scannen möchte.Scannen Sie eine Zeichenfolge weiter, bis sie das erste/letzte Vorkommen einer Zeichenfolge gefunden hat

axhaweacb 

Ich möchte den Text von "a" nach "b" bekommen. Dies ist mein aktuelles Muster:

pattern = "a.*?b"; 

Die aktuelle Ausgabe ist: axhaweacb (es ist alles, was dazwischen eine Aufnahme und b), aber was ich will zurück erhalten ist „acb“.

Warum Sie fragen können? Die Logik/Regex, die ich anwenden möchte, ist: Wenn Sie das erste Vorkommen der "von" Regex ("a") finden, starten Sie den Scanvorgang. Wenn Sie ein anderes Vorkommen des "von" Buchstaben finden, ohne das "letzte" Vorkommen eines Buchstabens zu finden - in diesem Fall "b", entfernen Sie die vorherige Zeichenkette - also axh, so dass die Zeichenkette zu: aweacb wird. Wenn Sie ein anderes Vorkommen von "von" finden - in diesem Fall a, ohne "to" zu finden - b. Entfernen Sie die vorherige Zeichenfolge, sodass sie acb wird. Dann scannen Sie erneut. In diesem Fall haben wir unser Muster gefunden - a bis b, ohne ein anderes "a" auf unserem Weg.

Ich weiß, dass ich die Zeichenfolge zu Anfang mit Teilstring und bis zum letzten Vorkommen von "a" abzustreifen kann - aber ich möchte dies auch für andere Strings wiederverwenden. Und in diesem Fall wird immer alles bis zum letzten Auftreten von etwas substringiert - was dazu führt, dass viele Daten entfernt werden.

Ich hoffe, ich habe meine Frage/Problem klar gemacht. Wenn nicht, bitte sag es mir und ich werde mein Bestes tun, um mein Problem zu klären.

Vielen Dank.

+0

Wissen Sie, dass die Zeichenfolge immer 3 Zeichen lang sein? In diesem Fall könnten Sie das Muster "a.b" verwenden. Ich weiß nicht, ob es für deine anderen Saiten verallgemeinert werden kann, aber du kannst darüber nachdenken. –

Antwort

1

Die Regex-Engine sucht nach einer Übereinstimmung von links nach rechts. Wenn es a mit a.*?b findet, ist es der erste a in Ihrer Zeichenfolge. Dann ist das erste gefundene und übereinstimmende b das letzte Zeichen in Ihrer axhaweacb Zeichenfolge.

Der Lazy Quantifier passt sich dem nächsten Zeichen am nächsten rechts an, das dem folgenden Submuster entspricht, nicht der kürzest mögliche Teilstring.

Also, was Sie brauchen, ist ein Weg, um auszuschließen sind (= nicht gefunden if) alle Vorkommen der führenden und Hinter Subpattern dazwischen.

Es kann mit Hilfe eines tempered greedy token erfolgen:

pattern = "a(?:(?!a|b).)*b"; 
      ^^^^^^^^^^^^^ 

hier ein demo

ist
+0

FYI, wenn Sie Zeilenumbrüche in Ihrer Eingabe haben, müssen Sie auch den DOTALL-Modifizierer angeben, damit '.' Zeilenumbrüchen entsprechen kann. –

0

können Sie diese negative Look-Ahead-basierte regex verwenden: alles

a(?:(?![ab]).)*b 
  • (?![ab]) sind die negativen regex passen aber a und B`
  • (?:(?![ab]).)* Matches 0 oder mehr von beliebigen Zeichen, das nicht a ist und b , thus giving us shortest match between a and b`

RegEx Demo

+0

Danke. Es funktioniert. Wie würde ich jedoch vorgehen, wenn ich diese Regex für verschiedene Strings wiederverwenden möchte, ohne die Regex jedes Mal ändern zu müssen. Wenn Sie zum Beispiel versuchen, "mein Name ist Jack" mit dieser Regex: name (?: (?! [Namejack]).) * Jack. Dies gibt "name is jack" zurück. Aber wenn ich versuche: meine (?: (?! [Myjack]).) * Buchse, um die ganze Zeichenfolge - es gibt nichts zurück. Irgendeine Idee warum? –

+0

Innerhalb '[...]' können Sie keine Mehrfachzeichenfolgen verwenden. Sie können verwenden: ['\ bname \ b (?: (?! \ B (Name | Jack) \ b).) * \ Bjack \ b'] (https://regex101.com/r/sH0xT2/3) – anubhava

Verwandte Themen