Esiste un metodo API che restituisce tutte le sottostringhe (possibilmente sovrapposte) che corrispondono a un'espressione regolare?Sottostringhe sovrapposte che corrispondono a un regex java
Ad esempio, ho una stringa di testo: String t = 04/31 412-555-1235;
e ho uno schema: Pattern p = new Pattern("\\d\\d+");
che corrisponde a stringhe di due o più caratteri.
Le partite ottengo sono: 04, 31, 412, 555, 1235.
Come posso ottenere le partite che si sovrappongono?
voglio il codice per tornare: 04, 31, 41, 412, 12, 55, 555, 55, 12, 123, 1235, 23, 235, 35.
Teoricamente dovrebbe essere possibile - c'è un ovvio algoritmo O(n^2)
che enumera e controlla tutte le sottostringhe sul modello.
EDIT
Piuttosto che enumerare tutte le stringhe, è più sicuro di utilizzare il metodo region(int start, int end)
in Matcher
. Il controllo del modello rispetto a una sottostringa separata e separata potrebbe modificare il risultato della corrispondenza (ad esempio se è presente un controllo di gruppo o di limite di parole non di cattura all'inizio/alla fine del modello).
EDIT 2
In realtà, non è chiaro se region()
fa quello che ci si aspetta per le partite di lunghezza zero. Le specifiche sono vaghe e gli esperimenti danno risultati deludenti.
Ad esempio:
String line = "xx90xx";
String pat = "\\b90\\b";
System.out.println(Pattern.compile(pat).matcher(line).find()); // prints false
for (int i = 0; i < line.length(); ++i) {
for (int j = i + 1; j <= line.length(); ++j) {
Matcher m = Pattern.compile(pat).matcher(line).region(i, j);
if (m.find() && m.group().size == (j - i)) {
System.out.println(m.group() + " (" + i + ", " + j + ")"); // prints 90 (2, 4)
}
}
}
Non sono sicuro di quale sia la soluzione più elegante è. Un approccio consisterebbe nel prendere una sottostringa di line
e eseguire il rilievo con i caratteri di limite appropriati prima di verificare se la corrispondenza di pat
corrisponde.
EDIT 3
Ecco la soluzione completa che mi è venuta. Può gestire modelli a larghezza zero, limiti, ecc. Nell'espressione regolare originale. Controlla tutte le sottostringhe della stringa di testo e controlla se l'espressione regolare corrisponde solo alla posizione specifica inserendo il modello con il numero appropriato di caratteri jolly all'inizio e alla fine. Sembra funzionare per i casi che ho provato - anche se non ho fatto test approfonditi. È sicuramente meno efficiente di quanto potrebbe essere.
public static void allMatches(String text, String regex)
{
for (int i = 0; i < text.length(); ++i) {
for (int j = i + 1; j <= text.length(); ++j) {
String positionSpecificPattern = "((?<=^.{"+i+"})("+regex+")(?=.{"+(text.length() - j)+"}$))";
Matcher m = Pattern.compile(positionSpecificPattern).matcher(text);
if (m.find())
{
System.out.println("Match found: \"" + (m.group()) + "\" at position [" + i + ", " + j + ")");
}
}
}
}
EDIT 4
Ecco un modo migliore di fare questo: https://stackoverflow.com/a/11372670/244526
EDIT 5
La biblioteca JRegex supporta trovare tutte le stringhe che si sovrappongono che corrispondono a un regex Java (anche se sembra non essere aggiornato da un po 'di tempo).In particolare, il documentation on non-breaking search specifica:
Utilizzando la ricerca non-breaking è possibile trovare tutte le possibili occureneces di un modello , compresi quelli che si intersecano o inserito. Questo è ottenuto utilizzando il metodo del Matcher procedere() al posto di find()
basta fare un ciclo post-regex attraverso tutti i risultati di 3 o più caratteri –
http://regexlib.com/ potrebbe essere un buon posto per fare un po 'di scavo. –
@ Ωmega Provando il mio meglio, ma aperto a feedback che non è utile. Saluti. –