Подтвердить что ты не робот

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

В следующем коде, если строка s добавлена ​​как 10 или 20 тысяч символов, ядро ​​Seg Mathematica отключается.

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

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

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

4b9b3361

Ответ 1

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

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

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

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

s = StringReplace[s,[email protected]".*MAGIC_STRING(?s).*"->""]

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

Ответ 2

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

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

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

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

Ответ 3

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."