【问题标题】:How to generate random strings that match a given regexp?如何生成与给定正则表达式匹配的随机字符串?
【发布时间】:2010-10-19 09:28:18
【问题描述】:

重复:

Random string that matches a regexp

不,不是。我正在寻找一种简单通用的方法,一种我可以实际实施的方法。这比随机生成密码要困难得多。


我想创建一个采用正则表达式的应用程序,并显示 10 个随机生成的与该表达式匹配的字符串。它应该帮助人们更好地理解他们的正则表达式,并决定他们是否足够安全以用于验证目的。有谁知道一个简单的方法来做到这一点?

一个明显的解决方案是编写(或窃取)一个正则表达式解析器,但这似乎超出了我的想象。

我再说一遍,我正在寻找一种简单且通用的方法来做到这一点。

编辑:蛮力方法是不可能的。假设随机字符串只是 [a-z0-9]{10} 和每秒 100 万次迭代,则需要 65 years 遍历所有 10 字符字符串的空间。

【问题讨论】:

  • 我不认为有一个简单的方法可以做到这一点......也许是机械土耳其人? :)
  • 您是否有特定的正则表达式,或者您是否在寻求任何正则表达式变体的通用解决方案?因为除非您将自己限制在没有任何扩展的真正正则表达式,否则您不会找到适用于 Perl 和 .NET 的表达式。
  • 好吧,我希望喜欢一个单一变体的通用解决方案,最值得注意的是我使用的那个,PHP 中的 Perl 正则表达式实现。
  • 一般来说,问题是#P-hard。 researchgate.net/publication/…

标签: regex parsing random reverse


【解决方案1】:

将您的正则表达式解析为DFA,然后随机遍历您的 DFA,直到您最终处于接受状态,为每个转换输出一个字符。每次遍历都会产生一个与表达式匹配的新字符串。

这不适用于不是真正正则的“正则”表达式,例如带有反向引用的表达式。这取决于你追求什么样的表达方式。

【讨论】:

  • @Richard E:确定性有限自动机
  • @Richard E:确定性有限自动机:en.wikipedia.org/wiki/Deterministic_finite_state_machine 基本上它是正则表达式的实现。当你编译一个正则表达式时,一个 DFA 就是结果。
  • @Richard E.,确定性有限自动机?
  • @DFA:如果您最终进入了 DFA 的非接受分支,并且没有任何转换以接受状态结束,那么您将不得不重新开始。显然,如果存在这样的分支,则必须以某种方式将其从状态集中剔除。使用图算法找到它们应该足够简单。
  • @Pies:这就是正则表达式的工作方式。即使你找到了一个为你做这件事的库,它也可能是这样工作的。它完全符合您的需要:遍历正则表达式所代表的结构,但相反;产生一个字符串而不是消耗一个。
【解决方案2】:

看看 Perl 的String::Random

【讨论】:

  • 我想你不知道 PHP 有类似的事情吗?
  • 用 Perl 编写,用一些 Perl-to-executable 工具编译它,然后从 PHP 调用它。
  • 互联网是一系列管子。
  • 是的,我想如果你使用单一语言,部署起来会更容易:)
  • Perl 的 String::Random 只支持一小部分正则表达式,所以我必须寻找更好的东西。
【解决方案3】:

利用现有的正则表达式诊断选项可能会或可能不实用的一个相当丑陋的解决方案。一些正则表达式库能够找出正则表达式未能匹配的位置。在这种情况下,您可以使用实际上是一种蛮力形式,但一次使用一个字符并尝试获得更长(和更进一步匹配)的字符串,直到获得完全匹配。这是一个非常丑陋的解决方案。但是,与标准的蛮力解决方案不同,它在 ab 之类的字符串上失败还会告诉您是否存在匹配的字符串 ab.*(如果不存在,请停止并尝试 ac。如果是,请尝试更长的字符串)。这可能不适用于所有正则表达式库。

从好的方面来说,从教学的角度来看,这种解决方案可能非常酷。在实践中,它可能在效果上类似于 dfa 解决方案,但不需要考虑 dfa。

请注意,您不会希望在此技术中使用随机字符串。但是,如果您在树中跟踪您已测试的内容,则可以使用随机字符开始,因此效果是一样的。

【讨论】:

  • 有趣的想法,我去看看。
【解决方案4】:

如果您的唯一标准是您的方法简单且通用,那么没有什么比蛮力更容易或更通用的了。 :)

for (i = 0; i < 10; ++i) {
    do {
        var str = generateRandomString();
    } while (!myRegex.match(str));
    myListOfGoodStrings.push(str);
}

当然,这是一种非常愚蠢的做事方式,主要只是个玩笑。

我认为你最好的办法是尝试编写你自己的非常基本的解析器,只教它你期望遇到的东西(例如:字母和数字范围、重复/可选字符......别担心关于后视等)

【讨论】:

  • 我想要一个在时间结束前真正完成运行的算法。我当然希望它运行在 1 秒以下。
  • 嘿,你应该更具体一点:p 无论如何,我在回答的第二部分中已经考虑到了这个问题。
  • 编写我自己的解析器正是我想要避免的事情:)
【解决方案5】:

普遍性标准是不可能的。给定正则表达式"^To be, or not to be -- that is the question:$",不会有十个唯一的随机字符串匹配。

对于非退化情况:

moonshadow 到 Perl 的 String::Random 的链接就是答案。从标准输入读取 RegEx 并将十次 String::Random 调用的输出写入标准输出的 Perl 程序是微不足道的。使用 Perl2exe 将其编译为 Windows 或 Unix exe,然后从 PHP、Python 或其他任何方式调用它。

另见Random Text generator based on regex

【讨论】:

  • 你给出的例子对我来说当然不是一个退化的例子,而是一个非常简单的例子。第一个字符仅匹配“T”,第二个字符仅匹配“o”,依此类推。如果所有版本都一样,那就这样吧。
猜你喜欢
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
相关资源
最近更新 更多