2014-12-04 161 views
0

我剛剛開始使用Python,我試圖用雙引號和方括號分割字符串。在雙引號和方括號中分割字符串

例子:

10.223.157.186 - - [15/Jul/2009:14:58:59 -0700] "GET /assets/js/lowpro.js HTTP/1.1" 200 10469 

通緝結果:

ip: 10.223.157.186 
identity: - 
username: - 
time: [15/Jul/2009:15:50:35 -0700] 
request: "GET /assets/js/lowpro.js HTTP/1.1" 
status: 200 
size: 10469 

我想他們在 '空間' 分裂,但它也將[]""之間拆分部分。就像這樣:

['10.223.157.186', '-', '-', '[15/Jul/2009:14:58:59', '-0700]', '"GET', '/assets/js/lowpro.js', 'HTTP/1.1"', '200', '10469'] 

我見過像許多可能的解決方案:

  • shlex(我的蟒蛇不會導入)
  • data = line.strip().split('\"')

但給人一種說不出的輸出太老了 說實話我真的不明白這個正則表達式,我也不知道我是否可以導入就像是shlex。

+1

如果你沒有'shlex',你會介意告訴我們你正在運行的是什麼版本的Python(應該是Python在交互式提示符下輸出的第一個東西)? – Kevin 2014-12-04 21:08:31

+3

這可能是一個學習一些關於正則表達式的好機會...... – 2014-12-04 21:09:15

+0

我剛剛意識到你的問題說你想處理引號,但你的例子實際上並沒有這樣做。 – jpmc26 2014-12-04 22:32:04

回答

0

您可以使用正則表達式:

line = """10.223.157.186 - - [15/Jul/2009:14:58:59 -0700] "GET /assets/js/lowpro.js HTTP/1.1" 200 10469\n""" 

import re 

log_line = re.compile('(?P<ip>[^ ]*) (?P<identity>[^ ]*) (?P<username>[^ ]*) \\[(?P<time>[^\\]]*)\\] "(?P<request>[^"]*)" (?P<status>[^ ]*) (?P<size>[^ ]*)$') 

for key, value in log_line.match(line).groupdict().iteritems(): 
    print "%s: %s" % (key, value) 

你也可以使用一個分析器,通過@ jpmc26建議。

2

我要去反對「正則表達式穀物」,並說使用解析器;解析器是正則表達式之上的複雜度級別,通常使用正則表達式來定義其語法部分。我選擇的圖書館是pyparsing。你會使用這樣的:

>>> s = '10.223.157.186 - - [15/Jul/2009:14:58:59 -0700] "GET /assets/js/lowpro.js HTTP/1.1" 200 10469' 
>>> from pyparsing import ZeroOrMore, Regex 
>>> parser = ZeroOrMore(Regex(r'\[[^]]*\]') | Regex(r'"[^"]*"') | Regex(r'[^ ]+')) 
>>> for i in parser.parseString(s): print i 
... 
10.223.157.186 
- 
- 
[15/Jul/2009:14:58:59 -0700] 
"GET /assets/js/lowpro.js HTTP/1.1" 
200 
10469 

注意,標記的順序(這些Regex對象的東西)是很重要的。通過首先放置方括號和雙引號標記,它們優先。如果你把最後一個放在第一位,它就不能正常工作。這樣做的一個好處就是擴展比正則表達式更容易(只支持常規語言操作,除非你做了一堆瘋狂的查找工作)。例如,解析器可以幫助你分開那些括號或者引號,如果你決定想要的話,並且做一點工作,你可以改變解析器以允許嵌套括號或者引號。 (後者是真正的正則表達式不能做的事情。你也許能夠得到一個帶有環視擴展的正則表達式來做到這一點,但在我看來這並不值得。解析器更強大,而且在我經驗,更易於理解和使用。)

請注意,解析器不會返回一個列表或可迭代。它返回自己的特殊對象:

>>> parser.parseString(s) 
(['10.223.157.186', '-', '-', '[15/Jul/2009:14:58:59 -0700]', '"GET /assets/js/lowpro.js HTTP/1.1"', '200', '10469'], {}) 
>>> type(parser.parseString(s)) 
<class 'pyparsing.ParseResults'> 

我想我也應該解釋我的正則表達式。

  • \[[^]]*\]:這只是匹配一對方括號,可選地帶有中間的東西。 \[表示需要以方括號開始。[^]]字符類(只是正則表達式中的一組字符);外括號使它成爲一個角色類。 ^告訴它「字符列表中的其他內容」,內部]只是字符列表。所以這部分只是「除]以外的任何東西」。 *的意思是「零個或多個以前的東西」,所以它的意思是「零個或多個字符,而不是]」。最後是\],這意味着它需要以]結尾。初始的[和最後的]必須使用\進行轉義,因爲它們通常用於指示字符類。

  • "[^"]*":這幾乎與最後一個相同。 "表示它必須以雙引號開頭。 [^"]是和以前一樣的角色類;它意味着「除雙引號之外的任何內容」。 *仍然意味着「零或多個」。最後的"只是表示它必須以引用結尾。所以這只是「零個或多個包圍雙引號的字符」。

  • [^ ]+[^ ]是又一個同類的角色類。它只是意味着「除了空間以外的任何字符」,因爲字符列表是一個空格。 +的意思是「以前的一件或多件事」(類似於*,除了它至少需要一件)。所以這是「一個或多個非空間字符」。

Regex對象之間的操作者|只是「或」 -ing的不同的令牌一起,使得解析器只要它可以匹配這三種可能的令牌之一吐出的令牌。

+0

感謝您的快速回答! – user3523150 2014-12-05 08:12:07

+0

@ user3523150沒問題。如果我們的答案之一解決了您的問題,請考慮接受它。 – jpmc26 2014-12-05 21:48:52

相關問題