2013-10-14 62 views
0

如何使用正則表達式從系統日誌消息中提取程序名?我有一個Java流處理模塊,它接受正則表達式來處理系統日誌消息。使用正則表達式提取Java字段分隔子字符串

日誌行可以是:

2013-10-14T22:05:29+00:00 hostname sshd[6359]: Connection closed by 192.168.1.10 
2013-10-14T22:05:29+00:00 hostname sshd:3322 Connection closed by 192.168.1.10 
2013-10-14T22:05:29+00:00 hostname sshd/6359 Connection closed by 192.168.1.10 
2013-10-14T22:05:29+00:00 hostname sshd Connection closed by 192.168.1.10 
2013-10-14T22:05:29+00:00 hostname SSHD[1133] Connection closed by 192.168.1.10 
2013-10-14T22:05:29+00:00 hostname SSH.D[6359]: Connection closed by 192.168.1.10 

字符串提取過程應該是:利用由空間限定的第三子串,並提取子串,在[:/或空白結束

所以第4個日誌樣品中,將所提取的字符串將是sshd,第五SSHD和第六SSH.D。這是否可能與正則表達式?

編輯:

我試圖爲((?:[A-Za-z][A-Za-z0-9_.-]+)),它似乎工作,但說實話,我修改了一個例子正則表達式和使用的在線工具來調整它,直到它符合我的使用情況,但我不知道到底它是如何工作的。

+2

是的。這是可能的。你有什麼嘗試? – Mena

+0

我試過的是「((?:[A-Za-z] [A-Za-z0-9 _.-] +))」,它似乎工作,但說實話,我修改了一個示例正則表達式,並使用在線工具來調整它,直到它適合我的用例,但我不確定它是如何工作的。 –

回答

0

嘗試這樣:

String str = line.split(" ")[2].replaceAll("(.+)(\\[|\\:|\\/).+", "$1"); 

沒有測試它。

+0

我正在通過正則表達式在flume配置正則表達式攔截器,所以我不能使用Java庫/函數。 –

1

split應該做的工作:

String token = data.split(" +")[2].split("[\\[:/]")[0]; 
+0

我正在將flume配置中的正則表達式傳遞給正則表達式攔截器,所以我不能使用Java庫/函數。 –

+2

您將問題標記爲Java並且不能使用Java最常用的String類方法? – anubhava

+0

我將它標記爲Java,因爲我認爲正則表達式需要與Java兼容。我不認爲unix shell或Perl正則表達式語法對Java應用1:1。 –

0

我認爲你正在尋找的正則表達式是:

String regex = "([^\\[:/]+).*"; 

.*說來匹配0或多個任意字符。在點星號().*前面放置一對圓括號可創建一個可從匹配器中選擇的組。由於它是第一組圓括號,因此它由組號1引用。在括號內部是一個匹配包含OP中指定字符的一個或多個否定字符類[^]+的表達式,具體爲「[」,「: 「和」/「字符。

下面是一個示例應用程序測試的結果:

package com.stackexchange.stackoverflow; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class Question19370191 { 
    public static void main(String[] args) { 
     String regex = "([^\\[:/]+).*"; 
     Pattern pattern = Pattern.compile(regex); 

     List<String> lines = new ArrayList<>(); 
     lines.add("2013-10-14T22:05:29+00:00 hostname sshd[6359]: Connection closed by 192.168.1.10"); 
     lines.add("2013-10-14T22:05:29+00:00 hostname sshd:3322 Connection closed by 192.168.1.10"); 
     lines.add("2013-10-14T22:05:29+00:00 hostname sshd/6359 Connection closed by 192.168.1.10"); 
     lines.add("2013-10-14T22:05:29+00:00 hostname sshd Connection closed by 192.168.1.10"); 
     lines.add("2013-10-14T22:05:29+00:00 hostname SSHD[1133] Connection closed by 192.168.1.10"); 
     lines.add("2013-10-14T22:05:29+00:00 hostname SSH.D[6359]: Connection closed by 192.168.1.10"); 

     for(String line : lines) { 
      String field = line.split("\\s")[2]; 
      String extraction = ""; 
      Matcher matcher = pattern.matcher(field); 
      if(matcher.matches()) { 
       extraction = matcher.group(1); 
      } 

      System.out.println(String.format("Field \"%-12s\" Extraction \"%s\"", field, extraction)); 
     } 
    } 
} 

它輸出以下:

Field "sshd[6359]: " Extraction "sshd" 
Field "sshd:3322 " Extraction "sshd" 
Field "sshd/6359 " Extraction "sshd" 
Field "sshd  " Extraction "sshd" 
Field "SSHD[1133] " Extraction "SSHD" 
Field "SSH.D[6359]:" Extraction "SSH.D" 
+0

我正在通過正則表達式到另一個模塊作爲配置,所以不能使用拆分。 –

+0

這是否意味着每個輸入行實際上來自InputStream而不是列表? – axiopisty

+0

我想是的。正則表達式被傳遞給一個水槽代理作爲配置來與水槽的正則表達式攔截器一起使用。 –

0

,如果你的示例數據會完全像您提供:

(?:.+?\s){2}([\w\.]+).+$ 

解釋:

(?:.+?\s){2} ...匹配到第二空間

([^\s[:/]+) ...匹配任何不是 '', ':' 或 '/'

.+$ ......比賽進行到EOL

你想要什麼在捕獲組\1

+0

不適用於我。如果我把你的正則表達式和一個樣本日誌行並在這裏試用它:http://java-regex-tester.appspot.com/ - 你的正則表達式匹配整個行。 –