В следующем коде, если строка 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 ценились бы.
Система 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
Лучший способ оптимизации регекса зависит от внутренних особенностей механизма регекса системы Mathematica, но я бы определенно избавился от (.|\\\n)*
, как упомянул @Simon. Дело не только в чередовании - хотя почти всегда ошибочно иметь чередование, в котором каждая альтернатива соответствует точно одному символу; для этого и нужны классы символов. Но вы также фиксируете каждый символ при его совпадении (из-за круглых скобок), только для того, чтобы отбросить его при совпадении со следующим символом.
Беглое сканирование документации по регексу системы Mathematica не нашло ничего похожего на модификатор /s
(Singleline или DOTALL), поэтому я рекомендую старый добрый прием JavaScript, [\\\s\\\S]*
-- сопоставлять все, что является пробелом или все, что не является пробелом. Также может помочь добавление $
якоря в конец регекса:
"(^|\\n)[^\\n]*MAGIC_STRING[\\s\\S]*$"
Но лучшим вариантом, вероятно, будет не использовать регексы вообще. Я не вижу здесь ничего, что требовало бы их, и, вероятно, было бы намного проще и эффективнее использовать обычные функции системы Mathematica для манипулирования строками.
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."