Reputation: 437
I try to find a way to generate string that matches regex, for example, the following regex:
[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}
There are some perl modules on Cpan which I tried that doesn't work: -> String::Random -> Regexp::Genex
The String::Random shows () is not supported. Regex::Genex reports error on strings($regex) with this one.
Any help is appreciated!
Upvotes: 2
Views: 704
Reputation: 385590
If you want a general solution and you aren't will to work towards fixing String::Random, you could use a large number of monkeys.
use strict;
use warnings qw( all );
use feature qw( say );
my $pattern = qr/^[A-Z]{6}[A-Z2-9][A-NP-Z0-9](?:[A-Z0-9]{3})?\z/;
my $min_len = 0;
my $max_len = 15;
my @syms = map chr, 0x20..0x7E;
my $s;
while (1) {
$s = join '', map { $syms[rand(@syms)] } 1..$min_len+rand($max_len-$min_len+1);
last if $s =~ $pattern;
}
say $s;
This solution literally generates "completely" random strings until it find one that matches. It's an awful approach, and it can be quite slow.
You can speed it up the solution by restricting the random string generator (via $min_len
, $max_len
and @syms
). That said, the more you restrict these, the fewer patterns this solution will support. For example, using $min_len = 8; $max_len = 11; @syms = ( 'A'..'Z', '0'..'9' );
will be insanely faster for the example pattern, but using those parameters might prevent it from working for other patterns.
Also note that this approach skews the odds. Some matching strings are more likely to be generated than others. For example, the monkeys are incredibly more likely to produce A
than AAA
given ^[A-Z]{1,3}\z
.
Upvotes: 3
Reputation: 385590
String::Random is exactly what you want. The only catch is that it doesn't support (...)
(or (?:...)
).
Either work to get support for that added to String::Random for a general purpose solution, or write up a specific-purpose solution as follows:
use strict;
use warnings qw( all );
use feature qw( say );
my $s = '';
for (1..6) {
$s .= ('A'..'Z')[rand(26)];
}
$s .= ('A'..'Z', '2'..'9')[rand(34)];
$s .= ('A'..'N', 'P'..'Z', '0'..'9')[rand(35)];
for (1..rand(2)) {
for (1..3) {
$s .= ('A'..'Z', '0'..'9')[rand(36)];
}
}
say $s;
Upvotes: 1