0

所以我正在对 haxeflixel 进行一些清理工作,我需要验证一个 csv 映射,所以我使用正则表达式来检查它是否正常(不要提及结尾逗号,我知道那不是有效的 csv 但我想要允许它),我认为我有一个不错的正则表达式可以做到这一点,它似乎在闪存上运行良好,但是 c++ 崩溃,neko 给了我这个错误:运行 pcre_exec 时发生错误......这是我的正则表达式,对不起,它很长,但我不知道问题出在哪里...... ^(([ ]*-?[0-9]+[ ]*,?)+\r?\n?)+$ 如果有人知道可能发生了什么,我会很感激,谢谢,尼科

附言。我的正则表达式中可能存在用于检查 csv 的错误,但我可以弄清楚这些,这很有趣,我宁愿只知道具体可能导致这种情况的原因:)

编辑:啊,我刚刚注意到这不会发生在所有字符串上,一旦我将其缩小到哪些字符串,我会发布一个......至于我正在检查的内容,它基本上只是为了确保有没有奇怪的 xml 标头,或地图文件中的任何非整数值,基本上它应该验证这一点:

1,1,1,1

1,1,1,1

1,1,1,1

或这个:

1,1,1,1,

1,1,1,1,

1,1,1,1,

但不是:

xml 等等等等>

1,米,1,1

1,1,b,1

1,1,1,1

xml>

(是的,我知道那不是有效的 xml;))

编辑:它变得陌生:所以我试图确定是什么字符串使它崩溃,虽然这仍然不能解释法线贴图崩溃,但它肯定很奇怪,并且具有相同的结果:

发生的事情是:这将失败 .match() 测试,但不会崩溃:

a

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

虽然这会使程序崩溃:

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

1,*a*,1,1,1,1,1,1,1,1,1,1,1,1,1
4

1 回答 1

1

老实说,你写了我见过的最糟糕的正则表达式之一。它实际上看起来像是专门为尽可能慢而编写的。我写它不是为了冒犯你,而是为了表达你需要学习多少编写正则表达式(提示:编写你自己的正则表达式引擎是一个很好的练习)。

谈到你的问题,我想它只是内存不足(它非常占用内存)。我不确定为什么它只发生在 pcre 目标上(neko 和 cpp 目标都使用 pcre),但我想这是关于在 pcre 中运行的每个正则表达式的内存限制或其他目标中的一些启发式方法来纠正这种错误写的正则表达式。

我会建议一些类似的东西

~/^(( *-?[0-9]+ *,)* *-?[0-9]+ *,?\r?\n)*(( *-?[0-9]+ *,)* *-?[0-9]+ *,?\r?\n?)$/

在那里,“~/”和最后一个“/”是哈希正则表达式标记。

我没有对它进行广泛的测试,只是在你的样本上运行,但它应该可以完成这项工作(可能需要进行一些调整)。

另外,作为一个提示,我建议您在运行任何正则表达式之前先将文件拆分为行,这将降低内存使用率(或者您只需要在内存中保存部分文本)并简化您的正则表达式。

我还要注意,由于无论如何您都需要解析 csv(对于任何格式正确的输入,我猜这些输入在您的数据中很普遍),因此在实际解析时进行所有测试可能会快得多。

编辑:问题“为什么它会吃掉这么多内存”的答案

嗯,这不是一个简短的话题,这就是为什么我建议你编写自己的正则表达式引擎。实现上有一些差异,但通常想象 regexp 引擎是这样工作的:

  1. 解析您的正则表达式并构建所有可能状态的图表(状态基本上是一个符号值和许多指向可以跟随它的其他符号的链接)。
  2. 设置读取指针和状态指针对的列表,当前状态列表,由正则表达式初始状态和指向匹配字符串首字母的指针组成
  3. 设置指向符号字符串第一个符号的读指针
  4. 将状态指针设置为正则表达式的初始状态
  5. 从当前状态列表中取出一对并将其存储为当前状态和当前读取指针
  6. 在当前读取指针下读取符号
  7. 将它与当前状态链接到的状态中的符号匹配,并列出匹配的状态。
  8. 如果此列表中有最终的正则表达式状态,则转到 12
  9. 对于此列表中的每个项目,将一对下一个读取指针(即 current+1)和项目添加到当前状态列表
  10. 如果当前状态列表为空,则返回 false,因为字符串与正则表达式不匹配
  11. 到 6
  12. 在这里,在匹配正则表达式的最终状态下,返回 true,字符串匹配正则表达式。

当然,正则表达式引擎之间存在一些差异,其中一些消除了一些问题。当然,它们也有伪符号、分组,它们需要存储位置正则表达式和匹配的组,它们具有前瞻和后视以及分组引用,这使得它有点(相当不起眼的措施)更复杂,并迫使使用更多复杂的数据结构,但主要思想是相同的。所以,我们到了,从算法中可以清楚地看到你的问题。您对要匹配的内容越不具体,引擎将相同子字符串匹配为状态图中不同路径的机会就越大,它将以指数方式消耗更多的内存和处理器时间。尝试模拟正则表达式引擎如何在字符串 aaaaaab、ab、aa、aaaaaaaaaa、aaaaaaaaaaaaaaaaaaaaaaaaaaaa 上匹配正则表达式 (a+a+)+b(Don'

此外,值得注意的是,一些正则表达式引擎的处理方式略有不同,因此它们可以正确处理这种情况,但总有一些方法可以使正则表达式变得非常慢。

还有一点需要注意的是,我可能对确切的内存问题有过误解。在这种情况下,它也可能是处理器,在此之前它可能是内存/处理器启动的引擎限制,而不是系统内存不足。

于 2014-04-23T13:51:27.477 回答