我有一个字符串,它是一个键值对列表,如下所示:
Key=key1,Value=value1 Key=key2,Value=value2
我的一些价值观围绕着它们,所以我可以有类似的东西:
Key=key1,Value={"a":"b"}, Key=key2,Value=value2, Key=key3,Value={"c":{"d":"e"}}
我想创建一个正则表达式来匹配大括号中的值。我目前拥有的正则表达式是{[^ =] *},如果这些值中没有值,则该函数可用。
这会破坏它:
Key=key1,Value={"a=":"b"}, Key=key2,Value=value2, Key=key3,Value={"c":{"d":"e"}}
我尝试将我的正则表达式更改为{[^(Key =)] *},但这与它不匹配。
如果我可以假设Key =是新密钥的开头并且不会出现在正则表达式值中,我该如何修改我的正则表达式以匹配它?
答案 0 :(得分:3)
当前正则表达式的问题在于,您无法使用字符类中的字符串进行否定。这是字符类。所以这不会像您期望的那样工作:{[^(Key=)]*}
- 它匹配任何包含非(
,K
,e
,y
字符的字符串=
,)
,零次或多次,但您希望它匹配任何非Key=
的字符串。
您可以使用不同的递归方法来完成您的需要:
{(([^{}]|(?R))*)}
答案 1 :(得分:3)
忘记正则表达式。完成你想要用正则表达式做的事情将是容易出错和不可靠的。你总是会遇到一些你无法用正则表达式处理好的边缘情况。
你真正需要的是无上下文语法。使用pyparsing
。
>>> from pyparsing import OneOrMore, Regex, Optional
>>> pairListParser = OneOrMore(u'Key=' + Regex(u'[^,]+') + u',Value=' + Regex(u'[^, ]+') + Optional(Regex(u',? ')))
>>> x = u'Key=key1,Value={"a=":"b"}, Key=key2,Value=value2, Key=key3,Value={"c":{"d":"e"}}'
>>> pairListParser.parseString(x, parseAll=True)
([u'Key=', u'key1', u',Value=', u'{"a=":"b"}', u', ', u'Key=', u'key2', u',Value=', u'value2', u', ', u'Key=', u'key3', u',Value=', u'{"c":{"d":"e"}}'], {}
请注意,在上面的示例中,我假设键不能包含逗号(,
),并且该值不能包含逗号(,
)或空格()。我这样做是为了简单,但是使用
pyparsing
,可以重做解析器以允许这些情况。这只是一个完成工作的问题,而使用正则表达式,如果这些限制不适用,则在数学上不可能解析它。
然后你只需要取出结果。
>>> parsedX = pairListParser.parseString(x, parseAll=True)
>>> parsedXIter = iter(i for i in parsedX if i not in (u'Key=', u',Value=', u', '))
>>> result = dict(zip(parsedXIter, parsedXIter))
>>> result
{u'key3': u'{"c":{"d":"e"}}', u'key2': u'value2', u'key1': u'{"a=":"b"}'}
(可能有更好的方法来提取结果,但这很快且很脏。请注意,pyparsing
具有允许您在解析时丢弃某些元素或转换结果的功能。)
在dict
中获得结果后,您可以使用值执行任何操作:
for k, v in result.items():
m = re.match(u'^{(.+)}$', v)
if m:
print(m.groups())
我认为最好将它们解析为JSON或类似的东西,但重点是现在你已经切断了价值周围的所有东西,并且可以单独处理价值。
答案 2 :(得分:2)
只需使用下面的正则表达式
Value=({[^{}]*(?1)?})
演示:https://regex101.com/r/pJ8lO9/2
说明:
你需要一个CFG,你可以使用正则表达式(在编程方面)获得CFG解决方案
如需进一步阅读此声明,请查看:How can we match a^n b^n with Java regex?和 https://nikic.github.io/2012/06/15/The-true-power-of-regular-expressions.html
因为这个模式需要匹配平衡的花括号,形成:
a^n b^n
由于n是任意的,正则表达式(就数学而言)无法解决这个问题。我们需要一个CFG。 正则表达式(就编程而言)的解决方案是:
(a(?1)?b)
这是一种递归模式。 '(?1)'递归第一捕获组:'(a(?1)?b)'。和'?'是为了避免无限递归。 '(a(?1)b)'将无限地递归。所以'(?1)'有两个选项,'(a(?1)?b)'或空。在CFG表示法中,它表示为:
(?1) -> a(?1)b | ε
回到我们的解决方案。 'a'代表'{'和'b'代表'}',所以
({(?1)?})
我们需要将值放在括号内:
({[^{}]*(?1)?})
并用'Value ='
进行装饰Value=({[^{}]*(?1)?})