Ошибка в Mathematica: регулярное выражение относилось к очень длинной строке

В следующем коде, если строка s добавляется, чтобы быть чем-то как 10 или 20 тысяч символов, ядро Mathematica seg отказы.

s = "This is the first line.
MAGIC_STRING
Everything after this line should get removed.
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890123456789012345678901234567890
...";

s = StringReplace[s, RegularExpression@"(^|\\n)[^\\n]*MAGIC_STRING(.|\\n)*"->""]

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

10
задан dreeves 13 February 2010 в 14:39
поделиться

3 ответа

Система Mathematica использует синтаксис PCRE, поэтому в ней есть модификатор /s он же DOTALL он же Singleline, вы просто добавляете модификатор (?s) перед той частью выражения, в которой вы хотите его применить.

См. документацию по RegularExpression здесь: (разверните раздел "Дополнительная информация")
http://reference.wolfram.com/mathematica/ref/RegularExpression.html

Следующие опции задают параметры для всех следующих за ними элементов регулярного выражения:
(?i) считать прописные и строчные буквы эквивалентными (игнорировать регистр)
(?m) заставить ^ и $ соответствовать началу и концу строк (многострочный режим)
(?s) разрешить . совпадать с новой строкой
(?-c) unset options

Этот модифицированный ввод не приводит к краху системы Mathematica 7.0.1 (оригинал приводил), используя строку длиной 15,000 символов, выдавая тот же результат, что и ваше выражение:

s = StringReplace[s,RegularExpression@".*MAGIC_STRING(?s).*"->""]

Это также должно быть немного быстрее по причинам, объясненным @AlanMoore

8
ответ дан 3 December 2019 в 23:13
поделиться

Лучший способ оптимизации регекса зависит от внутренних особенностей механизма регекса системы Mathematica, но я бы определенно избавился от (.|\\\n)*, как упомянул @Simon. Дело не только в чередовании - хотя почти всегда ошибочно иметь чередование, в котором каждая альтернатива соответствует точно одному символу; для этого и нужны классы символов. Но вы также фиксируете каждый символ при его совпадении (из-за круглых скобок), только для того, чтобы отбросить его при совпадении со следующим символом.

Беглое сканирование документации по регексу системы Mathematica не нашло ничего похожего на модификатор /s (Singleline или DOTALL), поэтому я рекомендую старый добрый прием JavaScript, [\\\s\\\S]* -- сопоставлять все, что является пробелом или все, что не является пробелом. Также может помочь добавление $ якоря в конец регекса:

"(^|\\n)[^\\n]*MAGIC_STRING[\\s\\S]*$"

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

4
ответ дан 3 December 2019 в 23:13
поделиться

Mathematica - отличная игрушка для руководителей, но я бы не советовал пытаться делать с ней что-либо серьезное, например регулярные выражения для длинных строк или любые вычисления для значительных объемов данных (или там, где важна правильность). Используйте что-то проверенное и проверенное. Visual F # 2010 требует 5 миллисекунд и одной строки кода, чтобы получить правильный ответ без сбоев:

> let str =
    "This is the first line.\nMAGIC_STRING\nEverything after this line should get removed." +
      String.replicate 2000 "0123456789";;
val str : string =
  "This is the first line.
MAGIC_STRING
Everything after this li"+[20022 chars]

> open System.Text.RegularExpressions;;
> #time;;
--> Timing now on

> (Regex "(^|\\n)[^\\n]*MAGIC_STRING(.|\\n)*").Replace(str, "");;
Real: 00:00:00.005, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0
val it : string = "This is the first line."
2
ответ дан 3 December 2019 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: