我尝试多次匹配令牌,但是我只得到最后一次出现,我理解这是根据this answer的正常行为,但是我无法在那里找到解决方案在我的示例中。
我的文字看起来像这样:
&{dict1_name}= key1=key1value key2=key2value
&{dict2_name}= key1=key1value
因此基本上是多行,每行都有一个起始字符串,空格,然后是可变数量的密钥对。如果您想知道这是哪里来的,那是我要转换为python变量文件的机器人框架变量文件。
我将每行进行迭代以匹配密钥对并从中构造一个python字典。
我当前的正则表达式模式是:
&{([^ ]+)}=[ ]{2,}(?:[ ]{2,}([^\s=]+)=([^\s=]+))+
如上所述,这可以正确地获取字典名称,但密钥对仅与最后一次匹配。如何获取返回包含("dict1_name","key1","key1value"..."keyn","keynvalue")
的元组,以便随后可以对此进行迭代并像这样构造python字典:
dict1_name= {"key1": "key1value",..."keyn": "keynvalue"}
谢谢!
答案 0 :(得分:1)
您可以将两个正则表达式用于名称,将另一个用于项目,将第一个用于第一个空格之后的项目:
import re
lines = ['&{dict1_name}= key1=key1value key2=key2value',
'&{dict2_name}= key1=key1value']
name = re.compile('^&\{(\w+)\}=')
item = re.compile('(\w+)=(\w+)')
for line in lines:
n = name.search(line).group(1)
i = '{{{}}}'.format(','.join("'{}' : '{}'".format(m.group(1), m.group(2)) for m in item.finditer(' '.join(line.split()[1:]))))
exec('{} = {}'.format(n, i))
print(locals()[n])
输出
{'key2': 'key2value', 'key1': 'key1value'}
{'key1': 'key1value'}
说明
'^&\{(\w+)\}='
与'&'
匹配,后跟由花括号(\w+)
包围的单词'\{', '\}'
。第二个正则表达式匹配由'='
连接的任何单词。该行:
i = '{{{}}}'.format(','.join("'{}' : '{}'".format(m.group(1), m.group(2)) for m in item.finditer(' '.join(line.split()[1:]))))
创建字典文字,最后使用exec
创建具有所需名称的字典。您可以访问查询本地的字典的值。
答案 1 :(得分:1)
结合dict理解使用两个表达式:
import re
junkystring = """
lorem ipsum
&{dict1_name}= key1=key1value key2=key2value
&{dict2_name}= key1=key1value
lorem ipsum
"""
rx_outer = re.compile(r'^&{(?P<dict_name>[^{}]+)}(?P<values>.+)', re.M)
rx_inner = re.compile(r'(?P<key>\w+)=(?P<value>\w+)')
result = {m_outer.group('dict_name'): {m_inner.group('key'): m_inner.group('value')
for m_inner in rx_inner.finditer(m_outer.group('values'))}
for m_outer in rx_outer.finditer(junkystring)}
print(result)
哪个生产
{'dict1_name': {'key1': 'key1value', 'key2': 'key2value'},
'dict2_name': {'key1': 'key1value'}}
^&{(?P<dict_name>[^{}]+)}(?P<values>.+)
# the outer format
请参见a demo on regex101.com。还有第二个
(?P<key>\w+)=(?P<value>\w+)
# the key/value pairs
也请参见a demo for the latter on regex101.com。
其余的只是简单地对dict理解中的不同表达式进行排序。
答案 2 :(得分:1)
如您所指出的,您将需要解决捕获组仅捕获最后一个匹配这一事实。一种方法是利用文件中的行是可迭代的这一事实,并使用两种模式:一种用于“行名”,一种用于其多个键值对:*
env.readTextFile(params.get("input"))
.flatMap(someCsvRowParseFunction())
*诚然,由于您每行要进行两次搜索,因此效率低下。但是对于中等大小的文件,应该没问题。
结果:
import re
dname = re.compile(r'^&{(?P<name>\w+)}=')
keyval = re.compile(r'(?P<key>\w+)=(?P<val>\w+)')
data = {}
with open('input/keyvals.txt') as f:
for line in f:
name = dname.search(line)
if name:
name = name.group('name')
data[name] = dict(keyval.findall(line))
请注意,>>> from pprint import pprint
>>> pprint(data)
{'d5': {'key1': '28f_s', 'key2': 'key2value'},
'name1': {'key1': '5', 'key2': 'x'},
'othername2': {'key1': 'key1value', 'key2': '7'}}
与Unicode文字字符匹配。
示例输入keyvals.txt:
\w
答案 3 :(得分:0)
以Brad's answer为基础,我进行了一些修改。正如我在对他的答复的评论中提到的那样,它在空白行或注释行中失败。我对其进行了修改,以忽略这些内容并继续。我还添加了对空格的处理:现在它匹配字典名称中的空格,但是用下划线替换它们,因为python变量名中不能包含空格。按键是字符串,因此保持不变。
import re
def robot_to_python(filename):
"""
This function can be used to convert robot variable files containing dicts to a python
variables file containing python dict that can be imported by both python and robot.
"""
dname = re.compile(r"^&{(?P<name>.+)}=")
keyval = re.compile(r"(?P<key>[\w|:]+)=(?P<val>[\w|:]+)")
data = {}
with open(filename + '.robot') as f:
for line in f:
n = dname.search(line)
if n:
name = dname.search(line).group("name").replace(" ", "_")
if name:
data[name] = dict(keyval.findall(line))
with open(filename + '.py', 'w') as file:
for dictionary in data.items():
dict_name = dictionary[0]
file.write(dict_name + " = { \n")
keyvals = dictionary[1]
for k in sorted(keyvals.keys()):
file.write("'%s':'%s', \n" % (k, keyvals[k]))
file.write("}\n\n")
file.close()