![](/img/trans.png)
[英]regex catastrophic backtracking ; extracting words starts with capital before the specific word
[英]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=)]*}
-它匹配包含不包含(
, K
, e
, y
=
, )
零次或多次的字符的任何字符串,但是希望它匹配不是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.