2014-12-11 11 views
7

ho questo requisito - per una stringa di input come quello mostrato sottoSostituire più gruppi di cattura utilizzando regexp con java

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

desidero nudo i confini di parola abbinati (dove la coppia corrispondente è 8 o & o% ecc) e comporta la seguente

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

Questa lista di caratteri che viene utilizzato per le coppie possono variare es 8,9,%, # etc e solo le parole che corrispondono all'inizio e alla fine di ogni tipo saranno rimosse da quei caratteri, con lo stesso carattere incorporato nella parola rimanente dove si trova.

Utilizzando Java posso fare un modello come \\b8([^\\s]*)8\\b e la sostituzione di $ 1, per catturare e sostituire tutte le occorrenze di 8 ... 8, ma come faccio a fare questo per tutti i tipi di coppie?

posso fornire un modello come la \\b8([^\\s]*)8\\b|\\b9([^\\s]*)9\\b .. e così via, che corrisponderà tutti i tipi di coppie corrispondenti * 8,9, ..), ma come faccio a specificare un gruppo 'variabile' sostituzione -

per esempio se la partita è 9 ... 9, la sostituzione dovrebbe essere $ 2.

Posso ovviamente eseguirlo attraverso più di questi, ognuno sostituendo uno specifico tipo di coppia, ma mi chiedo se c'è un modo più elegante.

Oppure esiste un modo completamente diverso di affrontare questo problema?

Grazie.

risposta

3

Si potrebbe utilizzare la regex qui sotto e quindi sostituire i caratteri corrispondenti dai personaggi presenti all'interno dell'indice gruppo 2.

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

O

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

Java regex sarebbe,

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

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")); 

uscita:

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

Spiegazione:

  • (?<!\\S) lookbehind negativa, afferma che la partita non sarebbe stata preceduta da un carattere non-spazio.
  • (\\S) Cattura il primo carattere non spaziale e lo memorizza nell'indice di gruppo 1.
  • (\\S+) Cattura uno o più caratteri non spaziali.
  • \\1 Si riferisce al personaggio all'interno del gruppo catturato per primo.
  • (?=\\s|$) E la partita deve essere seguita da uno spazio o fine dell'ancora di linea.
  • Questo assicura che il primo carattere e l'ultimo carattere della stringa devono essere uguali. Se è così, quindi sostituisce l'intera partita dai caratteri presenti all'interno dell'indice gruppo 2.

Per questo caso specifico, è possibile modificare la regex sopra come,

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

Grazie. L'uso del riferimento posteriore e dei gruppi di cattura su 2, come suggerito da te e da un'altra persona, sembra averlo inchiodato. Sto usando il seguente (? ssen

+0

@ssen esattamente quello che hai ottenuto. Molto più ridotto uno '(?

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

Prova questo.Riporta con $1 o \1. Guarda 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]) 

Utilizzare questo se si hanno molti delimitatori.

Problemi correlati