views:

2381

answers:

8

How would you go about creating a random alpha-numeric string that matches a certain regular expression?

This is specifically for creating initial passwords that fulfill regular password requirements.

+3  A: 

If you have a specific problem, you probably have a specific regular expression in mind. I would take that regular expression, work out what it means in simple human terms, and work from there.

I suspect it's possible to create a general regex random match generator, but it's likely to be much more work than just handling a specific case - even if that case changes a few times a year.

(Actually, it may not be possible to generate random matches in the most general sense - I have a vague memory that the problem of "does any string match this regex" is the halting problem in disguise. With a very cut-down regex language you may have more luck though.)

Jon Skeet
The regexp is configurable, so I don't know which one it'll be. I can suspect as to the general content, though not the specifics.
Alvaro Rodriguez
this is a sincere question: is there a RegExp that doesn't have any string that matches it??? I can't think of one. Thanks!
Manuel
@Manuel: You could be right, I'm not sure.
Jon Skeet
@Manuel: `(?=a)(?!a)`? :p
Svish
+1  A: 

You'd need to write a string generator that can parse regular expressions and generate random members of character ranges for random lengths, etc.

Much easier would be to write a random password generator with certain rules (starts with a lower case letter, has at least one punctuation, capital letter and number, at least 6 characters, etc) and then write your regex so that any passwords created with said rules are valid.

workmad3
A: 

Presuming you have both a minimum length and 3-of-4* (or similar) requirement, I'd just be inclined to use a decent password generator.

I've built a couple in the past (both web-based and command-line), and have never had to skip more than one generated string to pass the 3-of-4 rule.

  • 3-of-4: must have at least three of the following characteristics: lowercase, uppercase, number, symbol
warren
A: 

It is possible (for example, Haskell regexp module has a test suite which automatically generates strings that ought to match certain regexes).

However, for a simple task at hand you might be better off taking a simple password generator and filtering its output with your regexp.

ADEpt
A: 

Use the accepted answer at http://stackoverflow.com/questions/54991/generating-random-passwords until it matches your regexp.

Alvaro Rodriguez
+11  A: 

Welp, just musing, but the general question of generating random inputs that match a regex sounds doable to me for a sufficiently relaxed definition of random and a sufficiently tight definition of regex. I'm thinking of the classical formal definition, which allows only ()|* and alphabet characters.

Regular expressions can be mapped to formal machines called finite automata. Such a machine is a directed graph with a particular node called the final state, a node called the initial state, and a letter from the alphabet on each edge. A word is accepted by the regex if it's possible to start at the initial state and traverse one edge labeled with each character through the graph and end at the final state.

One could build the graph, then start at the final state and traverse random edges backwards, keeping track of the path. In a standard construction, every node in the graph is reachable from the initial state, so you do not need to worry about making irrecoverable mistakes and needing to backtrack. If you reach the initial state, stop, and read off the path going forward. That's your match for the regex.

There's no particular guarantee about when or if you'll reach the initial state, though. One would have to figure out in what sense the generated strings are 'random', and in what sense you are hoping for a random element from the language in the first place.

Maybe that's a starting point for thinking about the problem, though!

Now that I've written that out, it seems to me that it might be simpler to repeatedly resolve choices to simplify the regex pattern until you're left with a simple string. Find the first non-alphabet character in the pattern. If it's a *, replicate the preceding item some number of times and remove the *. If it's a |, choose which of the OR'd items to preserve and remove the rest. For a left paren, do the same, but looking at the character following the matching right paren. This is probably easier if you parse the regex into a tree representation first that makes the paren grouping structure easier to work with.

To the person who worried that deciding if a regex actually matches anything is equivalent to the halting problem: Nope, regular languages are quite well behaved. You can tell if any two regexes describe the same set of accepted strings. You basically make the machine above, then follow an algorithm to produce a canonical minimal equivalent machine. Do that for two regexes, then check if the resulting minimal machines are equivalent, which is straightforward.

Ken
So far my simplified answer (Use the accepted answer at http://stackoverflow.com/questions/54991/generating-random-passwords until it matches your regexp) looks promising :)Voted you up for thoroughness though.
Alvaro Rodriguez
honestly i would just make a random password generator and have it keep generating till i got one that matched all my conditions ^-^
RCIX
A: 

Why not work the regexp backwards? A simple example: if your regexp is

/[a-zA-Z]{6}/

then you know you need 6 letters a-z or A-Z, so generate them. This can get fancier, of course and, depending on your needs, you may end up reverse-writing an entire regexp parser, but you can stop adding features when you've fulfilled your need.

Olie
+2  A: 

String::Random in Perl will generate a random string from a subset of regular expressions:

#!/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";
Chas. Owens