29

您将如何创建与某个正则表达式匹配的随机字母数字字符串?

这专门用于创建满足常规密码要求的初始密码。

4

8 回答 8

19

Perl 中的String::Random将从正则表达式的子集生成随机字符串:

#!/usr/bin/perl

use strict;
use warnings;

use String::Random qw/random_regex/;

print random_regex('[A-Za-z]{3}[0-9][A-Z]{2}[!@#$%^&*]'), "\n";
于 2009-03-16T00:00:05.050 回答
19

Welp,只是在沉思,但是生成与正则表达式匹配的随机输入的一般问题对我来说听起来是可行的,因为对随机的足够宽松的定义和对正则表达式的足够严格的定义。我正在考虑经典的正式定义,它只允许 ()|* 和字母字符。

正则表达式可以映射到称为有限自动机的正式机器。这样的机器是一个有向图,具有一个称为最终状态的特定节点,一个称为初始状态的节点,以及每条边上的字母表中的一个字母。如果一个单词可以从初始状态开始,并通过图中的每个字符标记一条边并在最终状态结束,则该单词被正则表达式接受。

可以构建图,然后从最终状态开始并向后遍历随机边,跟踪路径。在标准构造中,图中的每个节点都可以从初始状态到达,因此您无需担心会犯不可恢复的错误并需要回溯。如果您达到初始状态,请停止并读取前进的路径。那是您与正则表达式的匹配项。

但是,对于何时或是否会达到初始状态并没有特别的保证。人们必须弄清楚生成的字符串在什么意义上是“随机的”,以及在什么意义上你首先希望语言中的随机元素。

不过,也许这是思考问题的起点!

现在我已经把它写出来了,在我看来,重复解决选择以简化正则表达式模式可能会更简单,直到你得到一个简单的字符串。查找模式中的第一个非字母字符。如果它是 *,则将前面的项目复制几次并删除 *。如果它是 |,请选择要保留的 OR'd 项目中的哪个并删除其余项目。对于左括号,执行相同的操作,但要查看匹配的右括号后面的字符。如果您首先将正则表达式解析为树表示,这可能会更容易,这使得 paren 分组结构更易于使用。

对于那些担心决定一个正则表达式是否真的匹配任何东西的人来说,这相当于停止问题:不,正则语言的表现非常好。您可以判断是否有任何两个正则表达式描述了同一组接受的字符串。您基本上制作了上面的机器,然后按照算法生成规范的最小等效机器。对两个正则表达式执行此操作,然后检查生成的最小机器是否等效,这很简单。

于 2008-10-16T11:01:00.440 回答
6

如果你有一个特定的问题,你可能有一个特定的正则表达式。我会采用那个正则表达式,用简单的人类术语来计算它的含义,然后从那里开始工作。

我怀疑创建一个通用的正则表达式随机匹配生成器是可能的,但它可能比仅仅处理一个特定的案例要多得多的工作——即使这个案例每年改变几次。

(实际上,可能无法生成最一般意义上的随机匹配 - 我有一个模糊的记忆,“任何字符串是否与此正则表达式匹配”的问题是变相的停止问题。使用非常精简的正则表达式语言不过你可能会有更多的运气。)

于 2008-10-15T16:32:48.227 回答
4

我写了Parsley,它由 Lexer 和 Generator 组成。

  • Lexer 用于将类似正则表达式的字符串转换为标记序列。
  • 生成器使用这些令牌来生成定义数量的代码。
$generator = new \Gajus\Parsley\Generator();

/**
 * Generate a set of random codes based on Parsley pattern.
 * Codes are guaranteed to be unique within the set.
 *
 * @param string $pattern Parsley pattern.
 * @param int $amount Number of codes to generate.
 * @param int $safeguard Number of additional codes generated in case there are duplicates that need to be replaced.
 * @return array
 */
$codes = $generator->generateFromPattern('FOO[A-Z]{10}[0-9]{2}', 100);

上面的示例将生成一个包含 100 个代码的数组,每个代码都以“FOO”为前缀,后跟来自“ABCDEFGHKMNOPRSTUVWXYZ23456789”干草堆的 10 个字符和来自“0123456789”干草堆的 2 个数字。

于 2014-04-22T21:23:06.307 回答
3

这个 PHP 库看起来很有前途:ReverseRegex

像所有这些一样,它只处理正则表达式的一个子集,但它可以处理相当复杂的事情,比如英国邮政编码:

([A-PR-UWYZ]([0-9]([0-9]|[A-HJKSTUW])?|[A-HK-Y][0-9]([0-9]|[ABEHMNPRVWXY])?) ?[0-9][ABD-HJLNP-UW-Z]{2}|GIR0AA)

输出

D43WF
B6 6SB
MP445FR
P9 7EX
N9 2DH
GQ28 4UL
NH1 2SL
KY2 9LS
TE4Y 0AP
于 2013-04-12T10:36:03.037 回答
1

您需要编写一个字符串生成器,它可以解析正则表达式并生成随机长度的字符范围的随机成员等。

更容易编写具有某些规则的随机密码生成器(以小写字母开头,至少有一个标点符号,大写字母和数字,至少 6 个字符等),然后编写您的正则表达式,以便使用创建的任何密码上述规则有效。

于 2008-10-15T16:35:39.110 回答
0

假设您同时具有最小长度和 3-of-4*(或类似)要求,我只是倾向于使用像样的密码生成器。

我过去构建了一对(基于 Web 的和命令行的),并且从来不需要跳过多个生成的字符串来通过 3-of-4 规则。

  • 3-of-4:必须至少具有以下三个特征:小写、大写、数字、符号
于 2008-10-15T16:36:38.127 回答
0

这是可能的(例如,Haskell regexp 模块有一个测试套件,可以自动生成应该匹配某些正则表达式的字符串)。

但是,对于手头的简单任务,您最好使用简单的密码生成器并使用您的正则表达式过滤其输出。

于 2008-10-15T16:46:36.373 回答