我必须在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(',')
答案 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