如何修改正则表达式以匹配第0行或第1行的开头和结尾?

时间:2016-08-11 09:07:15

标签: regex scala

我想创建一个包含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种可能的情况?

2 个答案:

答案 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 demoScala 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)
}