3

我对“堆栈溢出”错误感到困惑——“堆栈空间不足(应用程序错误代码:12246)——当我执行“全部替换”时,我正在进入 BBEdit,搜索

(@article(((?!eprint|@article|@book).)*\r)*)pmid = {(.+)}((((?!eprint|@article|@book).)*\r)*(@|\r*\z))

并替换为

\1eprinttype = {pubmed}, eprint = {\4}\5

我可以手动使用这些相同的模式,一次一个地进行查找和替换,没有任何错误,即使匹配不再发生。我还可以通过处理较小的文件来避免错误。

我怀疑这是我的低效和草率的正则表达式编码的罪魁祸首,并且希望专家帮助更有效地做到这一点。我试图在 BibLaTeX 参考书目中找到所有没有eprint字段但有pmid字段的条目,并用相应的电子打印规范替换该pmid字段(使用eprintand eprinttype)。


更新:经过一些实验,我发现一种不同的方法是我唯一可以开始工作的方法。正在寻找

(?(?=@article(.+\r)+eprint = {(.+\r)+}\r*)(?!)|(@article(.+\r)+)pmid = {(.+)}((.+\r)+}\r*))

并替换为

\3eprinttype = {pubmed}, eprint = {\5}\6

成功了。唯一的问题是反向引用很脆弱,但我无法在 BBEdit 中使用命名反向引用。

4

2 回答 2

3

这可能是由最后一部分引起的灾难性回溯:

.)*\r)*(@|\r*\z))

如果你把它分解并简化,你基本上有 a .*、 a\r*和另一个\r*紧挨着的。\r现在想象一下输入末尾的一串字符:每个字符应该如何\r分配?这些小条款中的哪一个会吸收每个\r角色?如果你有\r\r\r\r\r,你可以吃掉所有 5 个\rs.*部分,而一个部分一个都不吃\r*......或者,你可以组成任何数量的排列仍然匹配。由于*是贪婪的,它会首先尝试填充.*,但如果失败,它必须继续尝试排列,直到其中一个起作用。因此,它可能会通过不必要的回溯占用大量资源,直到最终崩溃。

我不是正则表达式优化技术方面的专家,但如果我是你,我会从那里开始。

更新:

查看关于 PCRE 的维基百科文章

除非选择“NoRecurse”PCRE 构建选项(又名“--disable-stack-for-recursion”),否则调用应用程序或操作系统必须为 PCRE 分配足够的堆栈空间。...虽然 PCRE 的文档警告说“NoRecurse”构建选项使 PCRE 比替代方案慢,但使用它可以完全避免堆栈溢出的问题。

所以我认为灾难性的回溯是一个不错的选择。在更改 PCRE 的构建选项之前,我会尝试通过调整你的正则表达式来解决它。

于 2012-03-31T07:30:26.367 回答
0

显然这是一些错误。但是您可以尝试稍微更改一下表达式。在不知道需求的情况下很难优化表达式,但这里有一个猜测:

(@article(?:(?:(?!eprint|@article|@book|pmid)[^\r])*+\r)*+)pmid = {([^\n\r]+)}((?:(?:(?!eprint|@article|@book)[^\r])*+\r)*(?:@|\r*\z))

用。。。来代替:

\1eprinttype = {pubmed}, eprint = {\2}\3

BBEdit 似乎使用 PCRE,除非它(非常)过时,否则上述表达式应该是兼容的。

于 2012-03-31T12:06:36.893 回答