我想创建一个包含3个捕获组的正则表达式,以提取下面4种可能情况的信息:
val line1 = "127.0.0.1 ssl.google-analytics.com"
val line2 = "#127.0.0.1 ssl.google-analytics.com"
val line3 = "127.0.0.1 ssl.google-analytics.com # Comment"
val line4 = "#127.0.0.1 ssl.google-analytics.com # Comment"
val m = lineRegex.findFirstMatchIn(line2).get
line2.substring(m.start(1), m.end(1)) // Should be # or ""
line2.substring(m.start(2), m.end(2)) // Should be ssl.google-analytics.com
line2.substring(m.start(3), m.end(3)) // Should be # Comment or ""
我想出了:
val lineRegex = """(^#?).*(?:127\.0\.0\.1)\s+((?!-)[A-Za-z0-9-\.]{1,63}(?<!-)\.+[A-Za-z]{2,6})\s+(#?.*)""".r
但它与line1或line2不匹配。我需要更改什么才能使其适用于所有4种可能的情况?
答案 0 :(得分:2)
您需要将最后一个组设为可选(例如\s+(#?.*)
- &gt; (?:\s+(#?.*))?
),或者只使用*
量词与最后一个\s
:
val lineRegex = """(^#?).*(?:127\.0\.0\.1)\s+((?!-)[A-Za-z0-9-\.]{1,63}(?<!-)\.+[A-Za-z]{2,6})\s*(#?.*)""".r
^^
请参阅regex demo和Scala demo。
具有可选组的版本需要对组3进行空检查(因为它可能未初始化)(demo):
val lineRegex = """(^#?).*(?:127\.0\.0\.1)\s+((?!-)[A-Za-z0-9-\.]{1,63}(?<!-)\.+[A-Za-z]{2,6})(?:\s+(#?.*))?""".r
// ^^^^^^^^^^^^^^
val m = lineRegex.findFirstMatchIn(line2).get
//...
if (m.group(3) != null) println(m.group(3))
注意:您可以直接打印/使用m.group(N)
,无需获取子字符串。
答案 1 :(得分:1)
如果没有明确要求使用昂贵的RegEx,您可以通过非常轻松地处理字符串来获得所需的结果。
def processLineString(l: String): List[String] = {
val (p1, rest) = {
if (l.head == '#') (l.head.toString, l.tail)
else ("", l)
}
val (p2, p3, p4) = rest.split(" ").toList match {
case p2d :: p3d :: "#" :: p4d :: Nil => (p2d, p3d, "# " + p4d)
case p2d :: p3d :: Nil => (p2d, p3d, "")
}
List[String](p1, p2, p3, p4)
}