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
.
我看不出这里有什么矛盾。
这让我摸不着头脑...
以下代码说明了 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
.
我看不出这里有什么矛盾。