如果匹配组没有 match/work,则为空值
Null value if matching group does not match/work
是否有 regex
表达式 return 为空值或如果未找到匹配项则为空值?
例如,我有处理此日志行的正则表达式:
May 5 23:00:01 99.99.99.99 %FRA-8-333344: Built inbound UDP connection 9999888811 for outside:11.111.111.11/47747 (11.111.111.11/47747) to net-9999:22.22.22.22/53 (22.22.22.22/53)
但有时日志会有所不同,例如缺少一个值(例如:缺少连接 ID):
May 5 23:00:01 99.99.99.99 %FRA-8-333344: Built inbound UDP for outside:11.111.111.11/47747 (11.111.111.11/47747) to net-9999:22.22.22.22/53 (22.22.22.22/53)
我的问题是我想处理此更改,我的想法是 return 如果 regex
找不到值,则为空值。我的下一步是构建配置单元 table,因此从 regex
中提取的值必须具有正确的顺序,例如 UDP 值不能写在连接 ID 列上。
有人知道这个问题的解决方法吗?在 R 语言中解决方案非常简单 (str_extract_all) 和正则表达式数组,但在 Scala 中我无法处理..
第一个日志中的键值:
timestamp: May 5 23:00:01
Action: Built
protocol: UDP
connection_id: 9999888811
src_ip: 11.111.111.11
dst_ip: 22.22.22.22
src_port 47747
dst_port 53
来自第二个日志的键值:
timestamp: May 5 23:00:01
Action: Built
protocol: UDP
connection_id: **EMPTY/NULL/" "**
src_ip: 11.111.111.11
dst_ip: 22.22.22.22
src_port 47747
dst_port 53
如果有任何帮助,我将不胜感激:)
2017 年 6 月 28 日更新
我的正则表达式:https://regex101.com/r/4mtAtu/1
我的解决方案。我认为它会很慢:
case class logValues(time_stamp: String, action: String, protocol: String, connection_id: String, ips: String, ports: String)
def matchLog(x: String): logValues = {
val time_stamp = """^.*?(?=\s\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s%)""".r.findAllIn(x).mkString(",")
val action = """((?<=:\s)\w{4,10}(?=\s\w{2})|(?<=\w\s)(\w{7,9})(?=\s[f]))""".r.findAllIn(x).mkString(",")
val protocol = """(?<=[\w:]\s)(\w+)(?=\s[cr])""".r.findAllIn(x).mkString(",")
val connection_id = """(?<=\w\s)(\d+)(?=\sfor)""".r.findAllIn(x).mkString(",")
val ips = """(?<=[\d\w][:\s])(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?=\/\d+|\z| \w)""".r.findAllIn(x).mkString("|")
val ports = """(?<=\d/)(\d{1,6})(?=\z|[\s(])""".r.findAllIn(x).mkString("|")
val logObject = logValues(time_stamp, action, protocol, connection_id, ips, ports)
return logObject
}
因此,如果您要匹配一个不存在的可选组,您将获得该组的空值。我会像下面这样匹配,然后将潜在的 null 值包装在类型安全的选项中,然后从那里继续。
mshelton-mshelton@ val sampleRegex = """(\w+)-(\w+)?-(\w+)""".r
sampleRegex: scala.util.matching.Regex = (\w+)-(\w+)?-(\w+)
mshelton-mshelton@ val sampleRegex(a, b, c) = "aaa-bbb-ccc"
a: String = "aaa"
b: String = "bbb"
c: String = "ccc"
mshelton-mshelton@ val sampleRegex(a, b, c) = "aaa--ccc"
a: String = "aaa"
b: String = null
c: String = "ccc"
您正在编译六种不同的正则表达式模式,然后将输入字符串提交给六种不同的测试。另一种方法是为整个日志行创建一个正则表达式,并通过捕获组提取所需的信息。
您必须对此进行调整,因为您知道哪些部分是 variant/invariant,而我只有两个示例日志行可以使用。
val logPattern =
raw"^(.*)\s" + // timestamp
raw"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s%\S+\s" +
raw"(\w+)?\s\w+\s" + // action
raw"(\w+)?\s\w*\s*" + // protocol
raw"(\d+)?\s.*outside:" + // connection ID
raw"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/" + // src IP
raw"(\d+).*:" + // src port
raw"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/" + // dst IP
raw"(\d+)" // dst port
val logRE = logPattern.r.unanchored // only once
好处:效率更高,一切都在一个地方。缺点:如果一个部分不正确,整个模式可能会失败。 (注意:只编译一次正则表达式模式。不是每次传入新日志行时。)
提取现在更直接。
log_line match {
case logRE(ts,act,ptcl,cid,sip,sprt,dip,dprt) =>
LogValues(ts,act,ptcl,cid,s"$sip/$dip",s"$sprt/$dprt")
case _ => /* log line doesn't fit pattern */
}
您会注意到我将三个字段设为可选:action
、protocol
和 connection ID
。不捕获任何内容的可选捕获组 return null
虽然 String
值可以是 null
,但这不是好的做法。最好使用 Option[String]
代替。当我们这样做时,由于整个日志行可能无法通过模式识别,所以让我们也将 return 类型设为可选。
case class LogValues( time_stamp : String
, action : Option[String]
, protocol : Option[String]
, connection_id : Option[String]
, ips : String
, ports : String
)
log_Line match {
case logRE(ts,act,ptcl,cid,sip,sprt,dip,dprt) =>
Some(LogValues( ts
, Option(act)
, Option(ptcl)
, Option(cid)
, s"$sip/$dip"
, s"$sprt/$dprt" ))
case _ => /* log line doesn't fit pattern */
None
}
是否有 regex
表达式 return 为空值或如果未找到匹配项则为空值?
例如,我有处理此日志行的正则表达式:
May 5 23:00:01 99.99.99.99 %FRA-8-333344: Built inbound UDP connection 9999888811 for outside:11.111.111.11/47747 (11.111.111.11/47747) to net-9999:22.22.22.22/53 (22.22.22.22/53)
但有时日志会有所不同,例如缺少一个值(例如:缺少连接 ID):
May 5 23:00:01 99.99.99.99 %FRA-8-333344: Built inbound UDP for outside:11.111.111.11/47747 (11.111.111.11/47747) to net-9999:22.22.22.22/53 (22.22.22.22/53)
我的问题是我想处理此更改,我的想法是 return 如果 regex
找不到值,则为空值。我的下一步是构建配置单元 table,因此从 regex
中提取的值必须具有正确的顺序,例如 UDP 值不能写在连接 ID 列上。
有人知道这个问题的解决方法吗?在 R 语言中解决方案非常简单 (str_extract_all) 和正则表达式数组,但在 Scala 中我无法处理..
第一个日志中的键值:
timestamp: May 5 23:00:01
Action: Built
protocol: UDP
connection_id: 9999888811
src_ip: 11.111.111.11
dst_ip: 22.22.22.22
src_port 47747
dst_port 53
来自第二个日志的键值:
timestamp: May 5 23:00:01
Action: Built
protocol: UDP
connection_id: **EMPTY/NULL/" "**
src_ip: 11.111.111.11
dst_ip: 22.22.22.22
src_port 47747
dst_port 53
如果有任何帮助,我将不胜感激:)
2017 年 6 月 28 日更新
我的正则表达式:https://regex101.com/r/4mtAtu/1
我的解决方案。我认为它会很慢:
case class logValues(time_stamp: String, action: String, protocol: String, connection_id: String, ips: String, ports: String)
def matchLog(x: String): logValues = {
val time_stamp = """^.*?(?=\s\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s%)""".r.findAllIn(x).mkString(",")
val action = """((?<=:\s)\w{4,10}(?=\s\w{2})|(?<=\w\s)(\w{7,9})(?=\s[f]))""".r.findAllIn(x).mkString(",")
val protocol = """(?<=[\w:]\s)(\w+)(?=\s[cr])""".r.findAllIn(x).mkString(",")
val connection_id = """(?<=\w\s)(\d+)(?=\sfor)""".r.findAllIn(x).mkString(",")
val ips = """(?<=[\d\w][:\s])(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?=\/\d+|\z| \w)""".r.findAllIn(x).mkString("|")
val ports = """(?<=\d/)(\d{1,6})(?=\z|[\s(])""".r.findAllIn(x).mkString("|")
val logObject = logValues(time_stamp, action, protocol, connection_id, ips, ports)
return logObject
}
因此,如果您要匹配一个不存在的可选组,您将获得该组的空值。我会像下面这样匹配,然后将潜在的 null 值包装在类型安全的选项中,然后从那里继续。
mshelton-mshelton@ val sampleRegex = """(\w+)-(\w+)?-(\w+)""".r
sampleRegex: scala.util.matching.Regex = (\w+)-(\w+)?-(\w+)
mshelton-mshelton@ val sampleRegex(a, b, c) = "aaa-bbb-ccc"
a: String = "aaa"
b: String = "bbb"
c: String = "ccc"
mshelton-mshelton@ val sampleRegex(a, b, c) = "aaa--ccc"
a: String = "aaa"
b: String = null
c: String = "ccc"
您正在编译六种不同的正则表达式模式,然后将输入字符串提交给六种不同的测试。另一种方法是为整个日志行创建一个正则表达式,并通过捕获组提取所需的信息。
您必须对此进行调整,因为您知道哪些部分是 variant/invariant,而我只有两个示例日志行可以使用。
val logPattern =
raw"^(.*)\s" + // timestamp
raw"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s%\S+\s" +
raw"(\w+)?\s\w+\s" + // action
raw"(\w+)?\s\w*\s*" + // protocol
raw"(\d+)?\s.*outside:" + // connection ID
raw"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/" + // src IP
raw"(\d+).*:" + // src port
raw"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/" + // dst IP
raw"(\d+)" // dst port
val logRE = logPattern.r.unanchored // only once
好处:效率更高,一切都在一个地方。缺点:如果一个部分不正确,整个模式可能会失败。 (注意:只编译一次正则表达式模式。不是每次传入新日志行时。)
提取现在更直接。
log_line match {
case logRE(ts,act,ptcl,cid,sip,sprt,dip,dprt) =>
LogValues(ts,act,ptcl,cid,s"$sip/$dip",s"$sprt/$dprt")
case _ => /* log line doesn't fit pattern */
}
您会注意到我将三个字段设为可选:action
、protocol
和 connection ID
。不捕获任何内容的可选捕获组 return null
虽然 String
值可以是 null
,但这不是好的做法。最好使用 Option[String]
代替。当我们这样做时,由于整个日志行可能无法通过模式识别,所以让我们也将 return 类型设为可选。
case class LogValues( time_stamp : String
, action : Option[String]
, protocol : Option[String]
, connection_id : Option[String]
, ips : String
, ports : String
)
log_Line match {
case logRE(ts,act,ptcl,cid,sip,sprt,dip,dprt) =>
Some(LogValues( ts
, Option(act)
, Option(ptcl)
, Option(cid)
, s"$sip/$dip"
, s"$sprt/$dprt" ))
case _ => /* log line doesn't fit pattern */
None
}