正则表达式回溯整个单词



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

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"}'}

(可能有更好的方法来提取结果,但这既快速又肮脏。值得注意的是,dict具有允许您在解析时丢弃某些元素或转换结果的功能。

在CC_15中得到结果后,您可以对值执行任何操作:

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^n b^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=({[^{}]*(?1)?})

最新更新