princepawn has asked for the wisdom of the Perl Monks concerning the following question:

I recently was given a spec on how files would look that would come from one of our clients:
/\d{2}([A-Z]{2,5})[_](\d{2})(\d{2})(\d{4})/

And then I set about writing a program which would manually generate filenames matching that regular expression. However, I am sure I am not the first tom, larry, or randall (to steal from Damian Conway's clever quote) to want to do this sort of thing.

Has anyone written a module which generates text which will match a regular expression, or, stated like most of my posts: "No module exists for the generation of text which will match a regular expression" {grin}

  • Comment on Bidirectional Regular Expression Parsing and Matching Text Generation?
  • Download Code

Replies are listed 'Best First'.
Re: Bidirectional Regular Expression Parsing and Matching Text Generation?
by japhy (Canon) on Oct 24, 2000 at 18:21 UTC
    That would require travelling the regex node tree. It doesn't seem very possible, even with reading the results of re.pm output... I've thought about making a text-to-regex translator, but I stop everytime I think about it, since that would require parsing Perl in Perl, which is not a very nice idea. With simple regexes like yours, though, you can hack it together yourself. I honestly have no idea why I wrote this. It is far too much for such a simple problem.
    package MatchRegex; use strict; use vars qw( @ISA @EXPORT_OK @digits @alpha ); require Exporter; @ISA = 'Exporter'; @EXPORT_OK = qw( digits alpha UCalpha LCalpha ); @digits = (0..9); @alpha = ('a'..'z', 'A'..'Z'); sub digits { ref $_[0] and local @digits = @{shift()}; # could use my() my $len; if (!@_) { $len = 1 } elsif (@_ == 1) { $len = $_[0] } else { $len = $_[0] + rand($_[1] + 1 - $_[0]) } return map $digits[rand @digits], 1 .. $len; } sub LCalpha { local @alpha = @alpha[0..25]; α } sub UCalpha { local @alpha = @alpha[26..51]; α } sub alpha { ref $_[0] and local @alpha = @{shift()}; # could use my() my $len; if (!@_) { $len = 1 } elsif (@_ == 1) { $len = $_[0] } else { $len = $_[0] + rand($_[1] + 1 - $_[0]) } return map $alpha[rand @alpha], 1 .. $len; }
    And then:
    use MatchRegex qw( digits UCalpha ); $filename = join "", ( digits(2), # \d{2} UCalpha(2,5), # [A-Z]{2,5} '_', # _ digits(2), # \d{2} digits(2), # \d{2} digits(4), # \d{4} );
    This is a glorified "make a random string as per my request" module. It can be expanded. But it can't interpret your regex for you. That's left up to you. Maybe MJD or Ilya or someone else could help hack at the regex engine to make something like this more likely.

    $_="goto+F.print+chop;\n=yhpaj";F1:eval
      On the same note! One could make a similar module to generate a regex based on function calls:
      $regex = genregex( OR( [digits,alpha], [alpha,digits] ) ); # $regex is now qr/\d[a-zA-Z]|[a-zA-Z]\d/
      Holy expletives deleted, Batman! This looks like the dreaded OmniMark!

      $_="goto+F.print+chop;\n=yhpaj";F1:eval
RE: Bidirectional Regular Expression Parsing and Matching Text Generation?
by Albannach (Monsignor) on Oct 24, 2000 at 18:34 UTC
    FWIW, a quick search on CPAN for "random" uncovered String::Random which appears to have a simplified reverse regex string generator that would work with your sample. I haven't tested it though.