2014-12-11 4 views
7

ich diese Anforderung haben - für eine Eingangszeichenfolge wie die untenErsetzen mehrere Capture-Gruppen unter Verwendung von regulären Ausdruck mit Java

gezeigt
8This8 is &reallly& a #test# of %repl%acing% %mul%tiple 9matched9 9pairs 

Ich mag würde die angepassten Wortgrenzen strippen (wo das passende Paar 8 oder & oder% usw.) und werden in der folgenden

This is really a test of repl%acing %mul%tiple matched 9pairs 

Diese Liste von Zeichen resultieren, die zB variieren kann für die Paare verwendet wird 8,9,%, # etc und nur die Wörter, die mit jedem Typ am Anfang und am Ende übereinstimmen, werden von diesen Zeichen beraubt, wobei das gleiche Zeichen in das Wort eingebettet wird, das dort verbleibt, wo es ist.

Mit Java I, ein Muster wie \\b8([^\\s]*)8\\b und Ersatz als 1 $ tun kann alle Vorkommen von 8 ... 8, zu erfassen und zu ersetzen, aber wie soll ich tue dies für alle Arten von Paaren?

ich ein Muster wie \\b8([^\\s]*)8\\b|\\b9([^\\s]*)9\\b zur Verfügung stellen kann .. und so, dass alle Arten von passenden Paaren * 8,9, ..) entspricht, aber wie definiere ich eine ‚Variable‘ Ersatz Gruppe -

z.B Wenn die Übereinstimmung 9 ... 9 ist, sollte die Ersetzung $ 2 sein.

Ich kann natürlich durch mehrere von diesen laufen, jede ersetzt eine bestimmte Art von Paar, aber ich frage mich, ob es einen eleganteren Weg gibt.

Oder gibt es eine ganz andere Art, dieses Problem anzugehen?

Danke.

Antwort

3

Sie könnten die unten regex verwenden und dann von den Zeichen im Inneren des Gruppenindex 2.

(?<!\S)(\S)(\S+)\1(?=\s|$) 

ODER

(?<!\S)(\S)(\S*)\1(?=\s|$) 

Java regex wäre,

(?<!\\S)(\\S)(\\S+)\\1(?=\\s|$) 
die angepassten Zeichen ersetzen

DEMO

String s1 = "8This8 is &reallly& a #test# of %repl%acing% %mul%tiple 9matched9 9pairs"; 
System.out.println(s1.replaceAll("(?<!\\S)(\\S)(\\S+)\\1(?=\\s|$)", "$2")); 

Ausgang:

This is reallly a test of repl%acing %mul%tiple matched 9pairs 

Erläuterung:

  • (?<!\\S) Negative Lookbehind, behauptet, dass das Spiel nicht von einem Nicht-Leerzeichen vorangestellt werden würde.
  • (\\S) Erfasst der erste Nicht-Raumzeichen und speichert sie in Gruppenindex 1.
  • (\\S+) Captures ein oder mehrere Nicht-Raumzeichen.
  • \\1 Bezieht sich auf das Zeichen innerhalb der ersten erfassten Gruppe.
  • (?=\\s|$) Und der Übereinstimmung muss ein Leerzeichen oder Ende des Linienankers folgen.
  • Dies stellt sicher, dass das erste Zeichen und das letzte Zeichen der Zeichenfolge identisch sein müssen. Wenn ja, dann ersetzt sie das ganze Spiel durch die Zeichen, die 2.

Für diesen speziellen Fall in der Gruppenindex vorhanden sind, können Sie die oben regex als, modifizieren

String s1 = "8This8 is &reallly& a #test# of %repl%acing% %mul%tiple 9matched9 9pairs"; 
System.out.println(s1.replaceAll("(?<!\\S)([89&#%])(\\S+)\\1(?=\\s|$)", "$2")); 

DEMO

+1

Danke. Die Verwendung der von Ihnen und einer anderen Person vorgeschlagenen Rückseitenreferenz und der Erfassung von Gruppen auf 2 scheint dies zu bestätigen. Ich verwende Folgendes (? ssen

+0

@ssen genau das hast du. Viel reduzierter ein '(?

1
(?<![a-zA-Z])[8&#%9](?=[a-zA-Z])([^\s]*?)(?<=[a-zA-Z])[8&#%9](?![a-zA-Z]) 

Versuchen Sie dies. Ersetzen Sie mit $1 oder \1. Siehe Demo.

https://regex101.com/r/qB0jV1/15

(?<![a-zA-Z])[^a-zA-Z](?=[a-zA-Z])([^\s]*?)(?<=[a-zA-Z])[^a-zA-Z](?![a-zA-Z]) 

verwenden, wenn Sie viele Trennzeichen haben.

Verwandte Themen