Gibt es eine API-Methode, die alle (möglicherweise überlappenden) Teilstrings zurückgibt, die einem regulären Ausdruck entsprechen?Alle überlappenden Teilstrings entsprechen einem Java-Regex
Zum Beispiel habe ich eine Textzeichenfolge: String t = 04/31 412-555-1235;
, und ich habe ein Muster: Pattern p = new Pattern("\\d\\d+");
, die Zeichenfolgen aus zwei oder mehr Zeichen entspricht.
Die Spiele ich sind: 04, 31, 412, 555, 1235
Wie kann ich überlappende Matches bekommen?
Ich mag der Code zurück: 04, 31, 41, 412, 12, 55, 555, 55, 12, 123, 1235, 23, 235, 35.
Theoretisch sollte es möglich sein - Es gibt einen offensichtlichen O(n^2)
Algorithmus, der alle Teilstrings gegen das Muster auflistet und überprüft.
EDIT
vielmehr alle Substrings als aufzählt, ist es sicherer, die region(int start, int end)
Methode in Matcher
zu verwenden. Das Überprüfen des Musters gegen einen separaten extrahierten Teilstring kann das Ergebnis der Übereinstimmung ändern (z. B. wenn am Anfang/Ende des Musters eine nicht erfassende Gruppen- oder Wortgrenzenprüfung stattfindet).
EDIT 2
Eigentlich ist es unklar, ob region()
tut, was Sie für Null-Breite Matches erwarten. Die Spezifikation ist vage, und Experimente liefern enttäuschende Ergebnisse.
Zum Beispiel:
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)
}
}
}
Ich bin mir nicht sicher, was die eleganteste Lösung ist. Ein Ansatz wäre, einen Teilstring von line
zu nehmen und mit den entsprechenden Begrenzungszeichen zu füllen, bevor überprüft wird, ob der pat
übereinstimmt.
EDIT 3
Hier ist die vollständige Lösung, die ich mit aufkommen. Es kann Muster mit Nullbreite, Grenzen usw. im ursprünglichen regulären Ausdruck behandeln. Es durchsucht alle Teilzeichenfolgen der Textzeichenfolge und überprüft, ob der reguläre Ausdruck nur an der bestimmten Position übereinstimmt, indem das Muster mit der entsprechenden Anzahl von Platzhaltern am Anfang und Ende aufgefüllt wird. Es scheint für die Fälle zu funktionieren, die ich ausprobiert habe - obwohl ich noch nicht ausführlich getestet habe. Es ist sicherlich weniger effizient als es sein könnte.
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
Hier ist ein besserer Weg, dies zu tun: https://stackoverflow.com/a/11372670/244526
EDIT 5
Die JRegex Bibliothek unterstützt alle überlappende Teil der Suche nach einem java regex passend (obwohl es scheint, seit einer Weile nicht aktualisiert worden zu sein).Insbesondere gibt die documentation on non-breaking search:
Mit non-breaking Suche können Sie alle möglichen occureneces eines Muster zu finden, einschließlich derer, die sich schneiden oder verschachtelt. Dies ist erreicht mit der Matcher-Methode fortfahren() statt find()
tun Sie einfach eine Post-Regex-Schleife durch alle 3 oder mehr Zeichen Ergebnisse –
http://regexlib.com/ könnte ein guter Ort, um etwas zu graben. –
@ Ωmega Ich versuche mein Bestes, aber offen für Feedback, das nicht sinnvoll ist. Prost. –