/ / Przecięcie regex Java z backreference - java, regex

Przecięcie regex Java z backreference - java, regex

Próbuję utworzyć wyrażenie regularne w Javie do dopasowaniawzór określonego słowa, aby znaleźć inne słowa o tym samym wzorze. Na przykład słowo "ząb" ma wzór 12213, ponieważ zarówno powtórzenia "t" i "o". Chciałbym, aby wyrażenie regularne pasowało do innych słów, takich jak "zęby".

Oto moja próba użycia backreferencji. W tym konkretnym przypadku powinno się nie powieść, jeśli druga litera jest taka sama jak pierwsza litera. Ostatnia litera powinna być inna niż cała reszta.

String regex = "([a-z])([a-z&&[^1]])\2\1([a-z&&[^12]])";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher("tooth");

//This works as expected
assertTrue(m.matches());

m.reset("tooto");
//This should return false, but instead returns true
assertFalse(m.matches());

Sprawdziłem, czy działa na przykładach takich jak "toot", jeśli usunę ostatnią grupę, tj. Następującą, więc wiem, że backreferencje działają do tego momentu:

String regex = ([a-z])([a-z&&[^1]])\2\1";

Ale jeśli dodam ostatnią grupę do końca wzorca, to znaczy, że nie rozpoznaje ona już odnośników w nawiasach kwadratowych.

Czy robię coś złego, czy jest to błąd?

Odpowiedzi:

4 dla odpowiedzi № 1

Jeśli wydrukujesz wyrażenie regularne, dowiesz się, co to jestźle, backreferences w twoich grupach faktycznie ucieka przez Javę, by wytworzyć jakieś dziwne postacie. Dlatego nie działa zgodnie z oczekiwaniami. Na przykład:

m.reset("oooto");
System.out.println(m.matches());

drukuje również

prawdziwe

Również, && nie działa w wyrażeń regularnych, będziesz musiał użyć patrz przed siebie zamiast. To wyrażenie działa dla twojego przykładu powyżej:

String regex = "([a-z])(?!\1)([a-z])\2\1(?!(\1|\2))[a-z]";

Ekspresja (?!\1) patrzy w przyszłość, aby zobaczyć, że następna cecha nie jest pierwszą w wyrażeniu, bez przesuwania kursora regex do przodu.


4 dla odpowiedzi nr 2

Spróbuj tego:

(?i)b(([a-z])(?!2)([a-z])32(?!3)[a-z]+)b

Wyjaśnienie

(?i)           # Match the remainder of the regex with the options: case insensitive (i)
b             # Assert position at a word boundary
(              # Match the regular expression below and capture its match into backreference number 1
(              # Match the regular expression below and capture its match into backreference number 2
[a-z]          # Match a single character in the range between “a” and “z”
)
(?!            # Assert that it is impossible to match the regex below starting at this position (negative lookahead)
2             # Match the same text as most recently matched by capturing group number 2
)
(              # Match the regular expression below and capture its match into backreference number 3
[a-z]          # Match a single character in the range between “a” and “z”
)
3             # Match the same text as most recently matched by capturing group number 3
2             # Match the same text as most recently matched by capturing group number 2
(?!            # Assert that it is impossible to match the regex below starting at this position (negative lookahead)
3             # Match the same text as most recently matched by capturing group number 3
)
[a-z]          # Match a single character in the range between “a” and “z”
+              # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)
b             # Assert position at a word boundary

Kod

try {
Pattern regex = Pattern.compile("(?i)\b(([a-z])(?!\2)([a-z])\3\2(?!\3)[a-z]+)\b");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
for (int i = 1; i <= regexMatcher.groupCount(); i++) {
// matched text: regexMatcher.group(i)
// match start: regexMatcher.start(i)
// match end: regexMatcher.end(i)
}
}
} catch (PatternSyntaxException ex) {
// Syntax error in the regular expression
}

Zobacz, jak gra tutaj. Mam nadzieję że to pomoże.