scala匹配可选的字符集

时间:2016-03-23 23:02:43

标签: regex scala

我正在使用scala regex从URL中提取令牌

我的网址是http://www.google.com?x=10&id=x10_23&y=2 在这里我想在id前面提取x10的值。请注意_23是可选的,可能会也可能不会出现,但如果出现,则必须将其删除。

我写的正则表达式是

val regex = "^.*id=(.*)(\\_\\d+)?.*$".r
x match {
    case regex(id) => print(id)
    case _ => print("none")
}

这应该有效,因为(\\_\\d+)?应该使_23成为一个整体。

所以我不明白它为什么不打印。

2 个答案:

答案 0 :(得分:1)

请注意,由于第一个贪婪点匹配子模式,您的模式^.*id=(.*)(\\_\\d+)?.*$实际上将x10_23&y=2放入组1中。由于(_\d+)?是可选的,因此第一个贪婪子模式不必为该捕获组生成任何字符。

您可以使用

val regex = "(?s).*[?&]id=([^\\W&]+?)(?:_\\d+)?(?:&.*)?".r
val x = "http://www.google.com?x=10&id=x10_23&y=2"
x match {
    case regex(id) => print(id)
    case _ => print("none")
}

请参阅IDEONE demoregex demo

请注意,不需要定义^$ - 默认情况下,该模式会锚定在Scala中。 (?s)确保我们匹配完整的输入字符串,即使它包含换行符号。

答案 1 :(得分:1)

另一个想法是使用内置的URI Java类及其getQuery()方法,而不是使用正则表达式来提取令牌。在那里,您可以按=拆分查询,然后检查其中一个是否以id=开头并提取值。

例如(仅作为示例):

val x = "http://www.google.com?x=10&id=x10_23&y=2"
val uri = new URI(x)

uri.getQuery.split('&').find(_.startsWith("id=")) match {
    case Some(param) => println(param.split('=')(1).replace("_23", ""))
    case None => println("None")
}

我发现维护正则表达式更简单,但这只是我的想法!