我正在尝试使用点分隔字符串来编写正则表达式。例如,
"abc", "abc.def", "a.b.c.e.f"
都有效,但
"abc..def", ".abc", "abc."
无效
这是我在scala中的正则表达式代码
object Test {
def main(args: Array[String]) {
val TestPattern = "^([a-z]+)(\\.?[a-z]+)*".r
val x: String = "abc.def.hij"
x match {
case TestPattern(a,b) => println(a + b)
case _ => println("Not Found")
}
}
}
所以这是我的正则表达式,
"^([a-z]+)(\\.?[a-z]+)*".r
有两个组成部分,
1. Starts with a-z
2. Repeat (has 0 or 1 dot, one or more from a-z) zero or more times
但是,
Input: abc.def.hij
Output: abc.hij
我不明白为什么
.def
不会显示在我的输出中。
答案 0 :(得分:2)
使用重复的组,您只能获得最后一场比赛。
要全部使用,请使用findFirstMatchIn
或类似内容。
肯定有重复的问题。
scala> val r0 = "([a-z]+)".r.unanchored
r0: scala.util.matching.UnanchoredRegex = ([a-z]+)
scala> val m0 = r0 findFirstMatchIn x
m0: Option[scala.util.matching.Regex.Match] = Some(abc)
scala> val r1 = "(\\.?[a-z]+)".r.unanchored
r1: scala.util.matching.UnanchoredRegex = (\.?[a-z]+)
scala> val m1 = r1 findFirstMatchIn m0.get.after
m1: Option[scala.util.matching.Regex.Match] = Some(.def)
scala> r1 findFirstMatchIn m1.get.after
res2: Option[scala.util.matching.Regex.Match] = Some(.hij)
答案 1 :(得分:1)
如同其他答案中所示,您将始终获得多次匹配的组的最后一场比赛。这是底层Java正则表达式引擎的限制。
在您的情况下,首先拆分值并评估各个组可能更好:
scala> val nameSeparator="""\.""".r
nameSeparator: scala.util.matching.Regex = \.
scala> val namePart="""[a-z]+""".r
namePart: scala.util.matching.Regex = [a-z]+
scala> val parts=nameSeparator.split("abc.def.ghi")
parts: Array[String] = Array(abc, def, ghi)
scala> parts.forall(!namePart.unapplySeq(_).isEmpty)
res20: Boolean = true
最后一个表达式检查数组部分中的所有元素是否与正则表达式namePart匹配。
如果你有一个更复杂的问题(例如表达式以前缀开头,那么有多个组具有不同的分隔符,然后是后缀),最好直接切换到解析器组合器:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.util.parsing.combinator.RegexParsers
object NameParser extends RegexParsers {
def separator : Parser[String] = """\.""".r
def namePart : Parser[String] = """[a-z]+""".r
def name : Parser[List[String]] = repsep(namePart, separator)
def apply(input: String) = parseAll(name, input)
}
// Exiting paste mode, now interpreting.
import scala.util.parsing.combinator.RegexParsers
defined module NameParser
scala> NameParser("abc.def.ghi")
res24: NameParser.ParseResult[List[String]] = [1.12] parsed: List(abc, def, ghi)
该示例可以很容易地适应更复杂的解析器。如果你需要一些错误处理,解析器组合器可以比正则表达式更容易扩展。
答案 2 :(得分:0)
您可以捕获完整组以及最后一组:
object Test {
def main(args: Array[String]) {
val TestPattern = """^([a-z]+(\.[a-z]+)*)""".r
val x = "abc.def.hij"
x match {
case TestPattern(a, b) => println(a)
case _ => println("Not Found")
}
}
}
编辑:
在三引号字符串中,不需要转义字符,因此 一个反斜杠就可以了。
“case TestPattern(a)”不起作用,因为参数数量必须与捕获组数量相同。
每个开放式paranthesis都会启动一个新的捕获组。 例如“”“^([a-z] +(\。[a-z] +))”“”。r有2个捕获组, “”(^ [([a-z] +(\。[a-z] +)))“”“。r有3。 所以后者将与TestPattern(a,b,c)匹配。- 醇>
由于在这种情况下不需要第二个捕获组,我们可以使用非捕获组,它以(?:而不是(。)开头。 当正则表达式变为“”(^([a-z] +(?:\。[a-z] +)*)“”“。r,TestPattern(a)=> println(a)有效。