2017-06-27 145 views
1

是任何regex表達式返回如果沒有找到匹配空或空值?Null值匹配組不匹配/工作

例如,我有正則表達式,其處理該日誌行:

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) 

我問題是我想處理這個變化,我的想法是返回空值,如果regex找不到價值。我的下一步是構建配置單元表,因此從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 

對於每一個幫助我將非常感激:)

UPDATE 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 
    } 
+1

你可以發佈你的當前正則表達式,它會匹配所有需要的值嗎? – thwiegan

+0

如果您正在使用組,那麼當調用相關的Matcher#group方法時,您應該能夠使索引或命名組匹配缺少的返回null的部分。這一切都取決於你的實施。 – Mena

+0

我想簡化一下:你好像想要在這兩種情況下都得到'connection_id:'來返回匹配,對吧?所以,你需要的只是''「」connection_id \ s *:\ s *(\ d *)「」「'並且第1組變量將被填充。 '\ d *'匹配0或更多數字,所以它會返回一個空字符串。 –

回答

0

您正在編譯六種不同的正則表達式模式,然後將輸入字符串提交給六個不同的測試。一種不同的方法是爲整個日誌行創建一個單一的正則表達式,並通過捕獲組提取所需的信息。

你必須調整這個,因爲你知道什麼部件株/不變的,我只有兩個示例日誌行的工作。

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,和connection ID。可選的捕捉組沒有捕獲任何返回null雖然它確定爲String值是null,這不是好的做法。改用Option[String]代替更好。儘管我們處於這種狀態,但由於整個日誌行可能無法識別模式,因此讓我們將返回類型設置爲可選。

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 
} 
0

因此,如果您匹配不存在的可選組,您將爲該組獲得空值。我會像下面一樣匹配,然後將可能爲null的值包含在類型安全選項中,然後從此處繼續。

[email protected] val sampleRegex = """(\w+)-(\w+)?-(\w+)""".r 
sampleRegex: scala.util.matching.Regex = (\w+)-(\w+)?-(\w+) 
[email protected] val sampleRegex(a, b, c) = "aaa-bbb-ccc" 
a: String = "aaa" 
b: String = "bbb" 
c: String = "ccc" 
[email protected] val sampleRegex(a, b, c) = "aaa--ccc" 
a: String = "aaa" 
b: String = null 
c: String = "ccc" 
+0

檢查我的正則表達式,我使用了向前看和向後看。 – jesky