2014-12-04 154 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

相关问题