在下面的代码中,如果字符串s附加为10或2万个字符,则Mathematica内核会出错。
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错误的想法。
答案 0 :(得分:8)
Mathematica使用PCRE语法,因此它确实具有/s
又名DOTALL
又名单行修饰符,您只需将(?s)
修饰符添加到您希望它所在的表达式部分之前应用。
请参阅此处的RegularExpression文档:(展开标有“更多信息”的部分)
http://reference.wolfram.com/mathematica/ref/RegularExpression.html
以下所有正则表达式元素的设置选项:
(?i)
将大写和小写视为等效(忽略大小写)
(?m)
使^和$匹配行的开始和结束(多行模式)
(?s)
允许。匹配换行符
(?-c)
未设置选项
这个修改后的输入不会让Mathematica 7.0.1崩溃(原来的),使用长度为15,000个字符的字符串,产生与表达式相同的输出:
s = StringReplace[s,RegularExpression@".*MAGIC_STRING(?s).*"->""]
@AlanMoore解释
的原因也应该快一点答案 1 :(得分:4)
优化正则表达式的最佳方法取决于Mathematica的正则表达式引擎的内部结构,但我绝对会像@Simon提到的那样摆脱(.|\\n)*
。这不仅仅是交替 - 尽管每个选项只匹配一个字符的交替几乎总是错误的;这就是角色类的用途。但是当你匹配它时,你也会捕获每个角色(因为括号),只有当你匹配下一个角色时才把它扔掉。
对Mathematica正则表达式文档的快速扫描没有出现像/s
(单行或DOTALL)修饰符,所以我建议旧的JavaScript待机,[\\s\\S]*
- 匹配任何< em>是空格或不是空格的任何内容。此外,将$
锚点添加到正则表达式的末尾可能会有所帮助:
"(^|\\n)[^\\n]*MAGIC_STRING[\\s\\S]*$"
但你最好的选择可能就是根本不使用正则表达式。我在这里看不到任何需要它们的东西,使用Mathematica的普通字符串操作函数可能会更容易也更有效。
答案 2 :(得分:2)
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."