2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
In regulären Ausdrücken? Es kann eine Menge darstellen, 0- oder 1-mal, entsprechend {0, 1}, oder es kann als Sonderzeichen zur Darstellung anderer Bedeutungen verwendet werden.
?, gefolgt von anderen Mengenqualifizierern, weist auf eine nicht gierige Übereinstimmung hin, d. h. auf eine Übereinstimmung mit der kürzestmöglichen Zeichenfolge, die gesucht wird.
Schauen wir uns ein Beispiel an:
- @Test
- public void test() {
- Pattern pattern = Pattern.compile("a.*?");
- Matcher matcher = pattern.matcher("abcabc");
- if (matcher.matches()) {
- System.out.println(matcher.group());
- }
- }
Ausgabe nach der Ausführung: abcabc
Ist es nicht das kürzeste Spiel? Warum ist es gescheitert?
Dabei handelt es sich tatsächlich um die Regeln des Non-Greedy-Matchings:Beim nicht gierigen Abgleich wird der kürzeste Pfad vor der nächsten Regel abgeglichen. Wenn es keine nächste Regel gibt, wird er als gieriger Abgleich verarbeitet.
Das heißt, wenn nur „a.*?“ erscheint, wird es trotzdem entsprechend dem Greedy-Matching verarbeitet.
Schauen wir uns die korrekte Verwendung an:
- @Test
- public void test() {
- Pattern pattern = Pattern.compile("(a.*?)(.*)");
- Matcher matcher = pattern.matcher("afcafc");
- if (matcher.matches()) {
- System.out.println(matcher.group(0));
- System.out.println(matcher.group(1));
- System.out.println(matcher.group(2));
- }
- }
Ausgabe nach der Ausführung:
- afcafc
- a
- fcafc
Wie Sie sehen können, erfasst die erste Erfassungsgruppe die kürzeste Zeichenfolge „a“ und die zweite Erfassungsgruppe erfasst „fcafc“.
Werfen wir einen Blick auf die beiden anderen Situationen:
Bei Verwendung in einer Erfassungsgruppe wird ?: vor dem regulären Ausdruck platziert, um eine Übereinstimmung, aber keine Erfassung anzuzeigen. Das heißt, diese Gruppe übereinstimmender Werte kann nicht über die Gruppenmethode abgerufen werden.
Sehen wir uns ein Beispiel an
- @Test
- public void test0() {
- Pattern pattern = Pattern.compile("\d{4}-(?:[a-z]+)");
- Matcher matcher = pattern.matcher("3214-opo");
- if (matcher.matches()) {
- System.out.println(matcher.group());
- System.out.println(matcher.group(1)); // 报错
- }
- }
Bei der Erfassung über Gruppe (1) wird ein Fehler gemeldet, d. h. es kann zwar abgeglichen, aber nicht erfasst werden. Wenn ?: entfernt wird, kann es normal über Gruppe (1) erfasst werden.
(?s) aktiviert den Einzelzeilenmodus auf der rechten Seite, sodass alle Zeichen übereinstimmen, einschließlich des Zeilenumbruchzeichens n.
Schauen wir uns ein Beispiel an:
- private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
-
-
- /**
- * 从输出结果可知,匹配到了换行符 'n'
- */
- @Test
- public void test4() {
- Pattern pattern = Pattern.compile(DEFAULT_VARIABLE_PATTERN);
- Matcher matcher = pattern.matcher("abcnsdf");
- if (matcher.matches()) {
- System.out.println(matcher.group());
- System.out.println(matcher.group(1));
- System.out.println(matcher.group(2)); // (?s) 不能作为捕获组,报错
- }
- }
Bei der Erfassung können (?s) nicht als Erfassungsgruppe erfasst werden, sodass „((?s).*)“ höchstens Gruppe (1) erfassen kann und beim Erfassen von Gruppe (2) ein Fehler gemeldet wird.
- @Test
- public void test5() {
- Pattern pattern = Pattern.compile("(.*)");
- Matcher matcher = pattern.matcher("abcnsdf");
- if (matcher.matches()) {
- System.out.println(matcher.group());
- System.out.println(matcher.group(1));
- }
- }
Versuchen Sie nach dem Entfernen der (?s), einen Abgleich mit „abcnsdf“ durchzuführen. Da ein Zeilenumbruchzeichen vorhanden ist, kann der Abgleich nicht abgeschlossen werden, sodass nichts ausgegeben wird.