正则表达式回溯整个单词

时间:2015-12-24 15:27:18

标签: python regex

我有一个字符串,它是一个键值对列表,如下所示:

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 =是新密钥的开头并且不会出现在正则表达式值中,我该如何修改我的正则表达式以匹配它?

3 个答案:

答案 0 :(得分:3)

当前正则表达式的问题在于,您无法使用字符类中的字符串进行否定。这是字符类。所以这不会像您期望的那样工作:{[^(Key=)]*} - 它匹配任何包含非(Key字符的字符串=),零次或多次,但您希望它匹配任何非Key=的字符串。

您可以使用不同的递归方法来完成您的需要:

{(([^{}]|(?R))*)}

Demo

答案 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)?})