2013-06-27 148 views
4

前一段时间我问了一个问题(Python splitting unknown string by spaces and parentheses),这很好地工作,直到我不得不改变我的思维方式。我仍然没有掌握正则表达式,所以我需要一些帮助。用括号分割Python的字符串

如果用户键入此:

new test (test1 test2 test3) test "test5 test6"

我想它看起来像输出到变量是这样的:

["new", "test", "test1 test2 test3", "test", "test5 test6"]

换句话说,如果它是一个单词由一个空格分隔,然后将它与下一个单词分开,如果它在括号中,则将整个单词分组在括号中并将其删除。引号也一样。

我目前使用此代码不符合上述标准(从上面的链接的答案):

>>>import re 
>>>strs = "Hello (Test1 test2) (Hello1 hello2) other_stuff" 
>>>[", ".join(x.split()) for x in re.split(r'[()]',strs) if x.strip()] 
>>>['Hello', 'Test1, test2', 'Hello1, hello2', 'other_stuff'] 

这种运作良好,但有一个问题,如果你有这样的:

strs = "Hello Test (Test1 test2) (Hello1 hello2) other_stuff"

它将Hello和Test合并为一个分裂而不是两个。

它也不允许同时使用圆括号和引号拆分。

+2

看看贪婪和非贪婪匹配。 – XORcist

+0

@möter你有链接可以引导我学习指导吗?我发现的大多数问题都是关于它的问题,并不能真正帮助我,而且我也无法阅读python文档。如果剩下的就只剩下它了。 – TrevorPeyton

+0

对不起,我误解了这个问题。但是,这里有一个官方教程的链接:http://docs.python.org/2/library/re.html – XORcist

回答

4

的回答很干脆什么:

re.findall('\[[^\]]*\]|\([^\)]*\)|\"[^\"]*\"|\S+',strs) 
1

您的问题没有明确定义。

你的规则描述是

换句话说,如果它是一个字由空格分隔然后从下一个字分成它 ,如果是在括号中然后分开单词的整个组 在括号中并将其删除。逗号也一样。

我猜逗逗你的意思是引号引号。

然后用这个

strs = "Hello (Test1 test2) (Hello1 hello2) other_stuff" 

你应该得到的是

["Hello (Test1 test2) (Hello1 hello2) other_stuff"] 
因为一切

被引号包围。最有可能的是,你希望不用关心最大的引号。

我提出这一点,虽然难看

import re, itertools 
strs = raw_input("enter a string list ") 

print [ y for y in list(itertools.chain(*[re.split(r'\"(.*)\"', x) 
     for x in re.split(r'\((.*)\)', strs)])) 
     if y <> ''] 

一个机器人得到

>>> 
enter a string list here there (x y) thereagain "there there" 
['here there ', 'x y ', ' thereagain ', 'there there'] 
+0

是的,对于逗号和引号以及我的措辞不太好的事实感到抱歉,这是一个漫长的夜晚。上面的代码除了一件事以外,我试图在这里解释'换句话说,如果它是一个由空格分隔的单词,那么将它从下一个单词中分离出来'就相当于你的'here there'在你的代码,并且应该被分成两个不同的单词“这里”,“那里”而不是“听到”。 – TrevorPeyton

1

这是在帮你想到

import re, itertools 
strs = raw_input("enter a string list ") 

res1 = [ y for y in list(itertools.chain(*[re.split(r'\"(.*)\"', x) 
     for x in re.split(r'\((.*)\)', strs)])) 
     if y <> ''] 

set1 = re.search(r'\"(.*)\"', strs).groups() 
set2 = re.search(r'\((.*)\)', strs).groups() 

print [k for k in res1 if k in list(set1) or k in list(set2) ] 
    + list(itertools.chain(*[k.split() for k in res1 if k 
    not in set1 and k not in set2 ])) 
+0

虽然如果我把'new test test(test1 test2)word word'test1 test2 tet3'te st''输出为'['test1 test2','test1 test2 tet3','test1 test2 tet3'新','单词','测试','单词','单词','te','st']'这几乎是正确的,但新单词不合适。 – TrevorPeyton

+0

对不起,我错过了这个订单实际上很重要 – octoback

+0

我以为这将是一个给定的,下次我会指定。这个代码有一个简单的解决方法吗? – TrevorPeyton

0

这是推动什么regexps可以做。考虑改用pyparsing。它确实递归下降。对于这个任务,你可以使用:

from pyparsing import * 
import string, re 

RawWord = Word(re.sub('[()" ]', '', string.printable)) 
Token = Forward() 
Token << (RawWord | 
      Group('"' + OneOrMore(RawWord) + '"') | 
      Group('(' + OneOrMore(Token) + ')')) 
Phrase = ZeroOrMore(Token) 

Phrase.parseString(s, parseAll=True) 

这是对奇怪的空白和处理嵌套括号强大。它比一个大的正则表达式更具可读性,因此更易于调整。

我知道你早就解决你的问题,但是这是对这类问题的最高谷歌排名的页面之一,pyparsing是根据著名的图书馆。