当我搜索时,我在BBEdit中遇到了一个"堆栈溢出"错误——"堆栈空间不足(应用程序错误代码:12246)"
(@article(((?!eprint|@article|@book).)*r)*)pmid = {(.+)}((((?!eprint|@article|@book).)*r)*(@|r*z))
并替换为
1eprinttype = {pubmed}, eprint = {4}5
我可以手动使用这些相同的模式,每次查找一个&替换,即使不再发生匹配,也不会出现任何错误。我还可以通过处理较小的文件来避免错误。
我怀疑这是我低效和草率的regex编码造成的,我希望专家能帮助我更有效地完成这项工作。我正在尝试查找BibLaTeX目录中尚未具有eprint
字段但具有pmid
字段的所有条目,并用相应的电子打印规范(使用eprint
和eprinttype
)替换pmid
字段。
更新:经过一些实验,我发现只有一种不同的方法才能发挥作用。搜索
(?(?=@article(.+r)+eprint = {(.+r)+}r*)(?!)|(@article(.+r)+)pmid = {(.+)}((.+r)+}r*))
并替换为
3eprinttype = {pubmed}, eprint = {5}6
真的很管用。唯一的问题是backreferences很脆弱,但我无法在BBEdit中使用命名的backreferences。
这可能是由最后一部分引起的灾难性回溯:
.)*r)*(@|r*z))
如果你把它分解并简化,你基本上有一个.*
、一个r*
和另一个紧挨着的r*
。现在在输入的末尾画一个r
字符串:每个r
应该如何分配?这些小子句中的哪一个会吸收每个r
字符?如果你有rrrrr
,你可以吃所有五个含有.*
成分的r
,而不吃任何含有r*
成分的。。。或者,你可以组成任意数量的仍然匹配的排列。由于*
是贪婪的,它会尝试首先填充.*
,但如果失败,它必须继续尝试排列,直到其中一个有效。因此,它可能会通过不必要的回溯占用你的大量资源,直到最终崩溃。
我不是regex优化技术的专家,但如果我是你的话,我会从那里开始。
更新:
查看维基百科上关于PCRE:的文章
除非"NoRecurse"PCRE构建选项(又名"--disable stack for recursion"),则必须有足够的堆栈空间由主叫应用程序或操作系统分配给PCRE。。。。虽然PCRE的文档警告说,"NoRecurse"构建选项使PCRE比其他选项慢,但使用它可以完全避免堆栈溢出的问题。
所以我认为灾难性的回溯是一个很好的选择。在更改PCRE上的构建选项之前,我会尝试通过调整正则表达式来解决这个问题。
显然这是个bug。但你可以试着稍微改变一下表达方式。在不知道需求的情况下很难优化表达式,但这里有一个猜测:
(@article(?:(?:(?!eprint|@article|@book|pmid)[^r])*+r)*+)pmid = {([^nr]+)}((?:(?:(?!eprint|@article|@book)[^r])*+r)*(?:@|r*z))
替换为:
1eprinttype = {pubmed}, eprint = {2}3
BBEdit似乎使用PCRE,除非它(非常)过时,否则上面的表达式应该是兼容的。