wake-up-neo.com

Regex optionale Erfassungsgruppe?

Nach stundenlangem Suchen entschied ich mich, diese Frage zu stellen. Warum funktioniert dieser reguläre Ausdruck: ^(dog).+?(cat)? nicht so, wie ich es mir vorgestellt habe (erfassen Sie den ersten Hund und die erste Katze, falls vorhanden)? Was vermisse ich hier?

dog, cat
dog, dog, cat
dog, dog, dog
19
forsajt

Der Grund, warum Sie nach einem widerwillig qualifizierten .+? Kein optionales cat erhalten, ist, dass es sowohl optional als auch nicht verankert ist: Die Engine ist nicht gezwungen, dieses Match zu machen, weil es kann Behandle das cat legal als den "Schwanz" der Sequenz .+?.

Wenn Sie die Katze am Ende des Strings verankern, d. H. ^(dog).+?(cat)?$ verwenden, erhalten Sie eine Übereinstimmung.

Pattern p = Pattern.compile("^(dog).+?(cat)?$");
for (String s : new String[] {"dog, cat", "dog, dog, cat", "dog, dog, dog"}) {
    Matcher m = p.matcher(s);
    if (m.find()) {
        System.out.println(m.group(1)+" "+m.group(2));
    }
}

Dies druckt ( Demo 1 )

dog cat
dog cat
dog null

Weißt du zufällig, wie du damit umgehen sollst, falls es etwas nach Katze gibt?

Sie können damit umgehen, indem Sie einen kniffligeren Ausdruck erstellen, der mit etwas anderem als cat übereinstimmt.

^(dog)(?:[^c]|c[^a]|ca[^t])+(cat)?

Jetzt könnte das cat irgendwo in der Zeichenkette ohne Anker vorkommen ( Demo 2 ).

20
dasblinkenlight

Die Antwort von @ dasblinkenlight ist großartig, aber hier ist ein regulärer Ausdruck, der den zweiten Teil verbessert, wenn er/sie gefragt wird

Weißt du zufällig, wie du damit umgehen sollst, falls es etwas nach Katze gibt?

Für den regulären Ausdruck ^(dog)(.+(cat))? müssten Sie die Gruppennummer erfassen. 3 statt 2, um die optionale Katze zu erhalten, funktioniert aber genauso gut ohne die Trickserei von Char zu Char.

Und hier ist die Demo (die wiederum aus der @ dasblinkenlight-Demo stammt, mit der ich diese Lösung basteln und finden konnte, nochmals vielen Dank!)

6
maltalef

Die Erweiterung von @ figha kann noch etwas erweitert werden, um die unnötige zweite Aufnahme zu vermeiden.

Verwenden Sie ?:, Um einen Teil eines Regex in Klammern nicht erfassbar zu machen. So wird der reguläre Ausdruck: ^(dog)(?:.+(cat))?

Wieder hier ist die erweiterte Demo und die Regex-Test .

3
mft25