在python中提取字符串的一部分

时间:2010-07-01 02:28:53

标签: python

我必须在python中解析输入字符串并从中提取某些部分。

字符串的格式是

(xx,yyy,(aa,bb,...)) // Inner parenthesis can hold one or more characters in it

我想要一个函数来返回xx,yyyy和一个包含aa,bb ...等的列表

我可以通过尝试分割括号和内容来做到这一点,但我想知道是否有一种从字符串中提取此类信息的正确pythonic方式

我有这个代码可行,但有更好的方法(没有正则表达式)

def processInput(inputStr):
    value = inputStr.strip()[1:-1]
    parts = value.split(',', 2)
    return parts[0], parts[1], (parts[2].strip()[1:-1]).split(',')

6 个答案:

答案 0 :(得分:3)

如果括号嵌套可以任意深度,那么regexen就不会这样做,你需要一个状态机或一个解析器。 Pyparsing支持使用前向声明类Forward:

的递归语法
from pyparsing import *

LPAR,RPAR,COMMA = map(Suppress,"(),")
nestedParens = Forward()
listword = Word(alphas) | '...'
nestedParens << Group(LPAR + delimitedList(listword | nestedParens) + RPAR)

text = "(xx,yyy,(aa,bb,...))"
results = nestedParens.parseString(text).asList()
print results

text = "(xx,yyy,(aa,bb,(dd,ee),ff,...))"
results = nestedParens.parseString(text).asList()
print results

打印:

[['xx', 'yyy', ['aa', 'bb', '...']]]
[['xx', 'yyy', ['aa', 'bb', ['dd', 'ee'], 'ff', '...']]]

答案 1 :(得分:3)

如果您对RE过敏,可以使用pyparsing

>>> import pyparsing as p
>>> ope, clo, com = map(p.Suppress, '(),')
>>> w = p.Word(p.alphas)
>>> s = ope + w + com + w + com + ope + p.delimitedList(w) + clo + clo
>>> x = '(xx,yyy,(aa,bb,cc))'
>>> list(s.parseString(x))
['xx', 'yyy', 'aa', 'bb', 'cc']
如果需要,

pyparsing还可以轻松控制结果的确切形式(例如,将最后3个项目分组到自己的子列表中)。但我认为最好的方面是多么自然(取决于你想要投入多少空间)你可以把“语法规范”读成:一个开放的paren,一个单词,一个逗号,一个单词,一个逗号,一个开放的paren,一个分隔的单词列表,两个封闭的括号(如果你发现上面s的作业不那么容易阅读,我想我不能选择更长的标识符; - )。

答案 2 :(得分:2)

让我们使用正则表达式!

/\(([^,]+),([^,]+),\(([^)]+)\)\)/

与之匹配,第一个捕获组包含xx,第二个包含yyy,在,上拆分第三个并且您有列表。

答案 3 :(得分:2)

这样怎么样?

>>> import ast
>>> import re
>>>
>>> s="(xx,yyy,(aa,bb,ccc))"
>>> x=re.sub("(\w+)",'"\\1"',s)
# '("xx","yyy",("aa","bb","ccc"))'
>>> ast.literal_eval(x)
('xx', 'yyy', ('aa', 'bb', 'ccc'))
>>>

答案 4 :(得分:1)

我不知道这更好,但这是一种不同的方式。使用之前建议的正则表达式

 def processInput(inputStr):
        value = [re.sub('\(*\)*','',i) for i in inputStr.split(',')]
        return value[0], value[1], value[2:]

或者,您可以使用两个链式替换函数来代替正则表达式。

答案 5 :(得分:0)

您的解决方案很不错(简单,高效)。如果您不信任您的数据源,则可以使用正则表达式来限制语法。

import re
parser_re = re.compile(r'\(([^,)]+),([^,)]+),\(([^)]+)\)')
def parse(input):
    m = parser_re.match(input)
    if m:
        first = m.group(1)
        second = m.group(2)
        rest = m.group(3).split(",")
        return (first, second, rest)
    else:
        return None

print parse( '(xx,yy,(aa,bb,cc,dd))' )
print parse( 'xx,yy,(aa,bb,cc,dd)' ) # doesn't parse, returns None

# can use this to unpack the various parts.
# first,second,rest = parse(...)

打印:

('xx', 'yy', ['aa', 'bb', 'cc', 'dd'])
None