你如何创建一个符合特定正则表达式的随机字母数字字符串?
这个问题是为了创建满足密码要求的初始密码。
你如何创建一个符合特定正则表达式的随机字母数字字符串?
这个问题是为了创建满足密码要求的初始密码。
嗯,只是思考,但对于足够松散的随机定义和足够严格的正则表达式定义,我认为生成匹配正则表达式的随机输入是可行的。我正在考虑经典的形式定义,它仅允许使用()|*和字母字符。
正则表达式可以映射到称为确定性有限状态自动机的形式机器中。这样的机器是一个带有特定节点的有向图,称为终态,一个称为初始状态的节点,并在每个边上用字母表示。如果可以从初始状态开始并通过图中标记为每个字符的一条边遍历到终止状态,则该单词将被正则表达式接受。
可以构建图,然后从终态开始向后遍历随机边缘,跟踪路径。在标准构造中,图中的每个节点都可以从初始状态到达,因此您无需担心犯下不可恢复的错误并需要回溯。如果到达初始状态,请停止并向前读取路径。那就是正则表达式的匹配结果。
但不能保证何时或是否会到达初始状态。必须弄清楚生成的字符串在什么意义上是“随机的”,以及在什么意义上您希望首先从语言中获得随机元素。
也许这是思考问题的起点!
现在我已经写出来了,我认为重复解析选择以简化正则表达式模式,直到剩下一个简单的字符串可能会更简单。找到模式中第一个非字母字符。如果它是*,则复制前面的项多次并删除*。如果是|,则选择保留OR的哪个项并删除其余项。对于左括号,做相同的事情,但查看匹配右括号后面的字符。如果首先将正则表达式解析为树表示形式,则可能更容易处理括号分组结构。
对于那些担心判断正则表达式是否匹配等同于停机问题的人来说,不,正则语言是相当规范的。你可以确定任何两个正则表达式是否描述了相同的接受字符串集。你基本上可以制作上面的机器,然后按照算法生成规范的最小等效机器。对于两个正则表达式做同样的事情,然后检查生成的最小机器是否等效,这很简单。
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";
我写了Parsley,它由Lexer和Generator组成。
$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);
这个 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
假设您需要满足最小长度和3-of-4*(或类似)要求,我会倾向于使用一个好的密码生成器。
我以前构建过几个(基于Web和命令行),从未不得不跳过超过一个生成的字符串才能通过3-of-4规则。
这是可能的(例如,Haskell正则表达式模块有一个测试套件,可以自动生成应该匹配某些正则表达式的字符串)。
然而,对于手头的简单任务,您最好使用简单的密码生成器,并使用您的正则表达式过滤其输出。