2011-11-01 27 views
3

我正在爲我公司的S3存儲桶設置一個ETL過程,以便我們可以跟蹤我們的使用情況,並且由於Amazon使用空格,雙引號和方括號,所以我在分解S3日誌文件列時遇到了一些麻煩劃分列。正則表達式來分割Amazon S3桶日誌的列?

我發現這個正則表達式:[^\\s\"']+|\"([^\"]*)\"|'([^']*)'對這個SO帖子:Regex for splitting a string using space when not surrounded by single or double quotes,這讓我非常接近。我只是需要幫助調整它忽略單引號和也之間的忽略空格「[」和「]」

這是我們從文件中的一個示例行:

dd8d30dd085515d73b318a83f4946b26d49294a95030e4a7919de0ba6654c362 ourbucket.name.config [31/Oct/2011:17:00:04 +0000] 184.191.213.218 - 013259AC1A20DF37 REST.GET.OBJECT ourbucket.name.config.txt "GET /ourbucket.name.config.txt HTTP/1.1" 200 - 325 325 16 16 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6" - 

而這裏的格式定義:http://s3browser.com/amazon-s3-bucket-logging-server-access-logs.php

任何幫助,將不勝感激!

編輯:爲了響應FaileDev,輸出應該是包含在兩個方括號之間的任何字符串,例如, [foo bar],兩個引號,例如「富酒吧」或空間,例如。FOO條(其中兩個foo和酒吧將分別匹配我已經打破了我在下面的塊中提供到它自己的行例行每場比賽:

dd8d30dd085515d73b318a83f4946b26d49294a95030e4a7919de0ba6654c362 
ourbucket.name.config 
[31/Oct/2011:17:00:04 +0000] 
184.191.213.218 
- 
013259AC1A20DF37 
REST.GET.OBJECT 
ourbucket.name.config.txt 
"GET /ourbucket.name.config.txt HTTP/1.1" 
200 
- 
325 
325 
16 
16 
"-" 
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6" 
- 
+0

究竟應該輸出什麼? – FailedDev

+0

我不敢相信更多人不需要這些信息!很好的問題,謝謝! – andy

回答

2

使用string.split你不能做到這一點,你需要通過「列」組中的所有捕獲迭代(如果你使用C#)

This matches a non-quoted, non-bracketed field: [^\s\"\[\]]+ 
This matches a bracketed field: \[[^\]\[]+\] 
This matches a quoted field: \"[^\"]+\" 

這是最簡單的匹配過程中留下的報價和括號,然後使用飾條趕走(「[ ','',''')

@"^((?<column>[^\s\"\[\]]+|\[[^\]\[]+\]|\"[^\"]+\")\s+)+$" 
+0

謝謝,ORing模式工作正常。此字符串模式最適合C#:@「([^ \ s \」「\ [\]] +)|(\ [[^ \] \ [] + \])|(\」「[^ \」 ] + \「」)「 –

+0

謝謝。似乎堆棧溢出刪除了我的斜槓....我忘了將它嵌入代碼塊中。現在更新。 –

2

這是一個愚蠢的正則表達式我寫來解析在節點S3的日誌文件:

/^(.*?)\s(.*?)\s(\[.*?\])\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(\".*?\")\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(\".*?\")\s(\".*?\")\s(.*?)$/ 

正如我所說,這是「啞巴」 - 它在很大程度上依賴於他們不要更改日誌格式,並且不包含任何每個字段奇怪的人物。

0

這是一個可以幫助某人的python解決方案。它也消除了引號和方括號你:

import re 
log = '79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be mybucket [06/Feb/2014:00:00:38 +0000] 192.0.2.3 79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be A1206F460EXAMPLE REST.GET.BUCKETPOLICY - "GET /mybucket?policy HTTP/1.1" 404 NoSuchBucketPolicy 297 - 38 - "-" "S3Console/0.4" -' 

regex = '(?:"([^"]+)")|(?:\[([^\]]+)\])|([^ ]+)' 

# Result is a list of triples, with only one having a value 
# (due to the three group types: '""' or '[]' or '') 
result = re.compile(regex).findall(log) 
for a, b, c in result: 
    print(a or b or c) 

輸出:

79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be 
mybucket 
06/Feb/2014:00:00:38 +0000 
192.0.2.3 
79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be 
A1206F460EXAMPLE 
REST.GET.BUCKETPOLICY 
- 
GET /mybucket?policy HTTP/1.1 
404 
NoSuchBucketPolicy 
297 
- 
38 
- 
- 
S3Console/0.4 
- 
[email protected]:~/Downloads$ python regex.py 
79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be 
mybucket 
06/Feb/2014:00:00:38 +0000 
192.0.2.3 
79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be 
A1206F460EXAMPLE 
REST.GET.BUCKETPOLICY 
- 
GET /mybucket?policy HTTP/1.1 
404 
NoSuchBucketPolicy 
297 
- 
38 
- 
- 
S3Console/0.4 
- 
0

我同意@andy!我不相信有更多的人不會處理S3的訪問日誌,考慮到他們已經有多久了。


這是我如果使用Node.js的,你可以使用我的模塊,使這個更容易對付使用

/(?:([a-z0-9]+)|-) (?:([a-z0-9\.-_]+)|-) (?:\[([^\]]+)\]|-) (?:([0-9\.]+)|-) (?:([a-z0-9]+)|-) (?:([a-z0-9.-_]+)|-) (?:([a-z\.]+)|-) (?:([a-z0-9\.-_\/]+)|-) (?:"-"|"([^"]+)"|-) (?:(\d+)|-) (?:([a-z]+)|-) (?:(\d+)|-) (?:(\d+)|-) (?:(\d+)|-) (?:(\d+)|-) (?:"-"|"([^"]+)"|-) (?:"-"|"([^"]+)"|-) (?:([a-z0-9]+)|-)/i 

正則表達式,或者將它移植到C#的基本思路都在那裏。

https://github.com/icodeforlove/s3-access-log-parser

0

我試着在C#中使用這一點,但發現有上述答案的一些不正確的字符,你不得不對非引用,非括號內場的正則表達式在末尾,否則它匹配的一切(使用http://regexstorm.net/tester): enter image description here

完整的正則表達式與括號內的第一字段,所述字段引用第二和非引述的,非括號字段最後: enter image description here

一個簡單的C#實現:

MatchCollection matches = Regex.Matches(contents, @"(\[[^\]\[]+\])|(""[^""]+"")|([^\s""\[\]]+)"); 
    for (int i = 0; i < matches.Count; i++) 
    { 
     Console.WriteLine(i + ": " + matches[i].ToString().Trim('[', ']', '"')); 
    }