python 断言背后的正则表达式否定,后续捕获的组开始和结束索引不正确?

python regex negative look behind assertion, subsequent captured group start and end indices incorrect?

这让我摸不着头脑...

以下代码说明了 python 2.7 中的问题:

import re

test_string = "wqdwc ww w w\nwcw w wef wefwe fq\nWrite {\ndfwdfwdc\ndfdfwdf wef we\nwefwe wefwe ewf\nwefdww {{ wefwe, wefwe, wef, } \n}\nwqef wefwef qw\n}\nwef qw qfg3g q g\ng332r256\n32e5\n"

node_descr_re = re.compile('\n([A-Z]\w+\d*)\s\{.+?(?<! )\n(\})', re.DOTALL)

node_descr_match = node_descr_re.search( test_string )

node_block = node_descr_match.group()

print("---------------------------")
print("Matched string: \n{}".format( node_block ))
print("---------------------------")
print("Node block length: {}".format( len(node_block) ))
print("group(2) start index: {}".format( node_descr_match.start(2) ))
print("group(2) end index: {}".format( node_descr_match.end(2) ))
print("group(2) capture: {}".format( node_descr_match.group(2) ))

我运行这个并得到:

---------------------------
Matched string: 

Write {
dfwdfwdc
dfdfwdf wef we
wefwe wefwe ewf
wefdww {{ wefwe, wefwe, wef, } 
}
wqef wefwef qw
}
---------------------------
Node block length: 99
group(2) start index: 129
group(2) end index: 130
group(2) capture: }

正则表达式正确地匹配了乱码中的节点描述,并正确地应用了断言背后的负面观察,忽略了 \n 的出现和前面有 space 的右大括号,但抓住了在随后的 \n 和右花括号之前没有 space。

打印语句的输出应该可以说明是什么困扰着我。它们表明 group(2) 已成功捕获节点描述的右大括号。但是虽然节点描述匹配(节点块)的整个长度是98个字符,但捕获的最终字符(group(2)捕获的右花括号)的起始索引是128 ????

任何人都可以解释一下吗?

编辑 - 索引是指匹配项在原始 test_string 中的位置吗?这似乎就是答案。很抱歉这个问题 - 我有时会对组的开始和结束索引感到困惑,这些索引指的是原始字符串中的位置而不是匹配本身

>>> test_string[129:]
'}\nwef qw qfg3g q g\ng332r256\n32e5\n'

这表明右大括号确实出现在索引 129 = node_descr_match.start(2) 处。请注意 node_block 本身也不从索引 0 开始。它从 31 开始:

>>> test_string.index("\nWrite")
31

node_block 整个 匹配项,因此跨越 test_string[31 : 31+99] = test_string[31 : 130]。右大括号是它的最后一个字符,所以从这个角度来看它的索引也必须是 130-1 = 129.

我看不出这里有什么矛盾。