python - 匹配和解析从复杂字符串中提取信息

  显示原文与译文双语对照的内容

我有一个函数的字符串,例如 'arg0, arg1=1, arg2=None',希望提取每个参数的名称和默认值。 我在处理简单案例时没有问题。 问题是字符串。列表和元组作为默认参数。 这是我目前的尝试


def get_args(s):
 regex = r'([a-zA-Z0-9._]*)s*=?s*(.*)'
 # save and replace quoted strings
 str_quoted = re.findall(r'(["'].*?["'])', s)
 for quote in str_quoted:
 s = s.replace(quote, '%s')
 # split arguments
 args = re.split("[ ]{0,10},[ ]{0,10}", s)
 # restore quoted strings
 args = ('n'.join(args) % tuple(str_quoted)).split('n')
 # return arguments
 return [{
 'name': re.match(regex, arg).group(1),
 'def': re.match(regex, arg).group(2)
 } for arg in args]

和一些示例字符串


s1 = 'arg0, arg1=1, arg2=None'
s2 = 'arg0, arg1=",", arg2=None'
s3 = 'arg0, arg1=[1, 2], arg2=[1, 2]'
s4 = 'arg0, arg1=(1, 2), arg2=(1, 2)'
s5 = 'arg0, arg1=[1, [1,2,3]], arg2=[1, 2]'

get_args(s1) 使用这个输出( 带有参数名称和默认值的字典列表)


[{'def': '', 'name': 'arg0'},
 {'def': '1', 'name': 'arg1'},
 {'def': 'None', 'name': 'arg2'}]

s2 也工作,但其他的。 我目前的字符串解决方案是临时替换它们( 请参见 str_quoted 部分) 。 我尝试了类似的列表或者元组,但很快遇到问题。

对于可靠地将参数与默认值分开的get_args 函数的任何建议?

时间: 作者:

在字符串的两边加上花括号,然后做 json.loads,你只需要处理一个字典。 忘记了。


arg_str = yourstring
arg_str = '{%s}' % arg_str
import json
dict_arg = json.loads(arg_str)

如果你得到错误,可以能是json只接受双引号,如果你的参数单引号替换它们,然后加载。

这是我给你的。 Martijn Pieters和它的他一些海报正确地说,正确的解析器是正确的方法。 我选择了一个简单的迭代,通过这些字符,处理上面的所有示例,更多和无限的嵌套。 也许没有那么优雅,但工作很好。 某些特殊情况仍未解决( 比如 。 转义符)


def get_args(s):
 # prepare
 syn = {'"': False,"'": False, '(': 0, '[': 0}
 mapping = {')': '(', ']': '['}
 args = []
 arg = {'name': '', 'def': ''}
 type = 'name'
 # iterate through chars
 for c in s:
 bracket = syn['('] == 0 and syn['['] == 0
 quote = (syn['"'] is True and c is not '"') or (syn["'"] is True and c is not"'")
 # add to argument definition
 if re.match(r"[a-zA-Z0-9._ ]", c) or quote:
 arg[type] += c
 # quotes
 elif re.match(r"["']", c):
 syn[c] = not syn[c]
 arg[type] += c
 # brackets
 elif re.match(r"[([]", c):
 syn[c] += 1
 arg[type] += c
 elif re.match(r"[)]]", c):
 syn[mapping[c]] -= 1
 arg[type] += c
 # '=' to define default value
 elif re.match(r"=", c) and bracket:
 type = 'def'
 # ',' to seperate arguments
 elif re.match(r",", c) and bracket:
 type = 'name'
 args.append({'name': arg['name'].strip(), 'def': arg['def'].strip()})
 arg = {'name': '', 'def': ''}
 else:
 arg[type] += c
 # add last arg
 if syn['('] == 0 and syn['['] == 0 and syn['"'] is False and syn["'"] is False:
 args.append({'name': arg['name'].strip(), 'def': arg['def'].strip()})
 # return
 return args

作者:
...