Scala: Matching optional Regular Expression groups
Asked Answered
N

2

16

I'm trying to match on an option group in Scala 2.8 (beta 1) with the following code:

import scala.xml._

val StatementPattern = """([\w\.]+)\s*:\s*([+-])?(\d+)""".r

def buildProperty(input: String): Node = input match {
    case StatementPattern(name, value) => <propertyWithoutSign />
    case StatementPattern(name, sign, value) => <propertyWithSign />
}

val withSign = "property.name: +10"
val withoutSign = "property.name: 10"

buildProperty(withSign)        // <propertyWithSign></propertyWithSign>
buildProperty(withoutSign)     // <propertyWithSign></propertyWithSign>

But this is not working. What is the correct way to match optional regex groups?

Niggling answered 17/3, 2010 at 10:31 Comment(0)
N
26

The optional group will be null if it is not matched so you need to include "null" in the pattern match:

import scala.xml._

val StatementPattern = """([\w\.]+)\s*:\s*([+-])?(\d+)""".r

def buildProperty(input: String): Node = input match {
    case StatementPattern(name, null, value) => <propertyWithoutSign />
    case StatementPattern(name, sign, value) => <propertyWithSign />
}

val withSign = "property.name: +10"
val withoutSign = "property.name: 10"

buildProperty(withSign)        // <propertyWithSign></propertyWithSign>
buildProperty(withoutSign)     // <propertyWithSign></propertyWithSign>
Niggling answered 17/3, 2010 at 12:0 Comment(3)
Scala uses Matcher.group method in Regex.unapplySeq. This specifies that if a group fails to match part of the sequence, null is returned - <java.sun.com/javase/6/docs/api/java/util/regex/…>Incuse
It would be nice if Scala could use an Option class for an optional regex field rather than requiring a null check.Grose
The order of case statements does matter: the statements matching null should be listed first, otherwise the sign variable will contain null.Gast
R
0

I don't see any problem with your regex. Although you need not escape the . in the char class.

EDIT:

You can try something like:

([\w.]+)\s*:\s*((?:+|-)?\d+)

To capture the name and value where the value can have an optional sign.

Rhody answered 17/3, 2010 at 10:41 Comment(2)
@Rhody thanks for pointing that out ;) The regex is fine, the problem is I cannot see who to match the optional group using the Scala pattern matching system. And I can find no examples to do so on the netNiggling
@codaaddict Thanks, that'll get my code working, but the Scala pattern matching question still remains :) I actually need different XML based on whether there is or is not a sign, so using the pattern matching system to extract and test if there is a sign seems like the cleanest solution to meNiggling

© 2022 - 2024 — McMap. All rights reserved.