[英]Node.JS Regex engine fails on large input
问题有点复杂,谷歌搜索并没有真正帮助。 我将尽力只涉及它的相关方面。
我有一个大约以下格式的大型文档:
样本输入 :
ABC is a word from one line of this document. It is followed by
some random line
PQR which happens to be another word.
This is just another line
I have to fix my regular expression.
Here GHI appears in the middle.
This may be yet another line.
VWX is a line
this is the last line
我想根据以下内容删除文本部分:
组成“From”的单词可以出现在一行中(看GHI)。 但是为了移除,需要移除整条生产线。 (需要删除包含GHI的整行,如下面的示例输出中所示)
样本输出 :
PQR which happens to be another word.
This is just another line
I have to fix my regular expression.
VWX is a line
this is the last line
上面的例子对我来说实际上似乎很容易,直到我针对非常大的输入文件运行它(49KB)
我尝试过的 :
我目前使用的正则表达式是(不区分大小写和多行修饰符):
^.*\b(abc|def|ghi)\b(.|\s)*?\b(pqr|stu|vwx)\b
问题
上面的正则表达式可以很好地处理小文本文件。 但是在大文件上失败/崩溃引擎。 我试过它反对下面:
StackoverflowError
(此问题末尾发布的堆栈跟踪) 实际输入:
我的正则表达式(为清晰起见,分为多行):
^.*\\\\b(patient demographics|electronically signed|md|rn|mspt|crnp|rt)\\\\b (.|\\\\s)*? \\\\b(history of present illness|hpi|chief complaint|cc|reason for consult|patientis|inpatient is|inpatientpatient|pt is|pts are|start end frequency user)\\\\b
题:
堆栈跟踪:
Exception in thread "main" java.lang.StackOverflowError
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4218)
at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
at java.util.regex.Pattern$Branch.match(Pattern.java:4114)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4357)
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
PS:我在这个问题上添加了几个标签,因为我已经在这些环境中尝试了它并且实验失败了。
问题是(。| \\ s)*因为任何空格字符都匹配,它将允许它向下移动两个选项。 这使它变得指数级增大。
你可以在ruby中看到这个正则表达式的问题
str = "b" + "a" * 200 + "cbab"
/b(a|a)*b/.match str
这需要永远,而基本相同
/ba*b/.match str
快速匹配。
你可以通过使用.*
或if来解决这个问题.
与换行符不匹配(.|\\n)*
我很想尝试简化这个。 目前说实话并不是很复杂但是如何:
\b(abc|def|ghi)\b.*\b(pqr|stu|vwx)\b
难道这仍然没有你想要的东西,但是线锚的开始和中间不必要的可选元素? 可能没有任何区别,但可能值得尝试。
我认为你的问题可能在于,随着文件变得越来越长,你可以匹配from和to的对,大约是nxm / 2.这意味着你会得到指数级更多的结果,占据越来越多的来源文件。 如果文件以ABC开头并以VWX结束,则其中一个匹配将是整个文件。
为了给正则表达式引擎减少匹配处理,我的第一种方法是分别仅对(abc|def|ghi)
和(pqr|stu|vwx)
进行正则表达式。 返回结果后,您可以查看匹配中的每个结果并尝试找到要阻止的第一个匹配项。 一些用于实现此目的的伪代码将是
from = regex.match(file, '(abc|def|ghi)')
to = regex.match(file, '(pqr|stu|vwx)')
for each match in from:
for index in to:
if index > match:
add index, match to results
break
for each result:
parse backwards to the beginning of the line
edit the file to remove the matching text
虽然这为自己创造了更多的工作,但这意味着正则表达式解析器不必将整个n kB文件同时保存在内存中,并且可以更有效地解析小块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.