Почему мой поиск в BBEdit вызывает ошибку «переполнение стека»? - PullRequest
3 голосов
/ 31 марта 2012

Я озадачен ошибкой "переполнения стека" - "нехватка стека (код ошибки приложения: 12246)", - которую я получаю в BBEdit при выполнении операции "заменить все" в поиске

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

и замена на

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

Я могу использовать эти же шаблоны вручную, выполняя поиск и замену по одному, без каких-либо ошибок, даже если совпадение больше не происходит. Я также могу избежать ошибки, работая с небольшими файлами.

Я подозреваю, что в этом виноват мой неэффективный и неаккуратный код регулярных выражений, и я был бы признателен за помощь эксперта в этом. Я пытаюсь найти все записи в библиографии BibLaTeX, которые еще не имеют поля eprint, но имеют поле pmid, и заменить поле pmid соответствующей спецификацией электронной печати (используя eprint и eprinttype).


Обновление: После некоторых экспериментов я обнаружил, что другой подход - единственное, что я могу заставить работать. Поиск

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

и замена на

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

делает свое дело. Единственная проблема в том, что обратные ссылки хрупкие, но я не могу заставить именованных обратных ссылок работать в BBEdit.

Ответы [ 2 ]

3 голосов
/ 31 марта 2012

Это, вероятно, катастрофический откат , вызванный этой последней частью:

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

Если вы разберетесь с этим и упростите его, у вас, по сути, будет .*, \r*,и еще один \r* прямо рядом друг с другом.Теперь изобразите строку из \r символов в конце ввода: как должен распределяться каждый \r?Какие из этих маленьких пунктов впитают каждый \r символ?Если у вас есть \r\r\r\r\r, вы можете съесть все пять \r с частью .* и ни одного вообще с частями \r* ... или вы можете создать любое количество перестановок, которые все еще будут совпадать.Поскольку * является жадным, он сначала попытается заполнить .*, но если это не удастся, он должен продолжать попытки перестановок, пока одна из них не сработает.Так что это, вероятно, затрачивает кучу ваших ресурсов с ненужным возвратом, пока, наконец, он не рухнет.

Я не эксперт по методам оптимизации для регулярных выражений, но я бы начал там, на вашем месте.

Обновление:

Ознакомьтесь с статьей в Википедии о PCRE :

Если только опция компоновки PCRE "NoRecurse" (aka "--disable-stack)-for-recursion "), вызывающее приложение или операционная система должны выделить достаточное пространство стека для PCRE.... Хотя документация PCRE предупреждает, что опция сборки "NoRecurse" делает PCRE медленнее, чем альтернатива, его использование полностью исключает проблему переполнения стека.

Так что я думаю, что катастрофический откат назад - хорошая ставка здесь,Я бы попытался решить эту проблему, настроив регулярное выражение перед изменением параметров сборки на PCRE.

0 голосов
/ 31 марта 2012

Очевидно, что это какая-то ошибка.Но вы могли бы попытаться немного изменить выражение.Трудно оптимизировать выражение, не зная требований, но вот предположение:

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

Заменить на:

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

BBEdit, похоже, использует PCRE, если только он (очень) не устарелВышеупомянутое выражение должно быть совместимым.

...