繁体   English   中英

正则表达式回溯整个单词

[英]regex backtracking entire word

我有一个字符串,它是键值对的列表,看起来像:

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 =是新密钥的开始并且不会出现在正则表达式值中,那么如何修改正则表达式以使其与此匹配?

当前正则表达式的问题在于,您不能对字符类中的字符串进行取反。 这是一个角色类。 因此,这将无法正常工作: {[^(Key=)]*} -它匹配包含不包含(Key =)零次或多次的字符的任何字符串,但是希望它匹配不是Key=任何字符串。

您可以对递归使用其他方法来完成所需的工作:

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

演示版

忘记正则表达式。 完成您想用正则表达式执行的操作将容易出错且不可靠。 您总是会遇到一些用正则表达式无法很好处理的小巧情况。

您真正需要的是上下文无关的语法。 使用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或类似的东西会更好,但是重点是您已经切断了值周围的所有内容,并且可以单独使用值。

只需使用下面的正则表达式

Value=({[^{}]*(?1)?})

演示: https : //regex101.com/r/pJ8lO9/2

说明:

您需要一个CFG,并且可以使用正则表达式获得CFG解决方案(就编程而言)

要进一步了解此声明,请检查: 我们如何将a ^ nb ^ n与Java正则表达式匹配? 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)?})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM