I'm trying to add functionality to an existing script that sends files to customers. The problem is we have dozens, possibly hundreds in near future, of customers who want the files we send them to match their specific naming convention. As such, I'm trying to make our script generic and allow a series of regex patterns to be defined in an INI per client. We have it working EXCEPT for capture groups, which are not interpolating at all--it always remains as $1, $2 ... $n. Here is a script showing the basic concept of what we've tried (and failed) when dealing with capture groups.
my $s = "foo1bar"; $s =~ /(\w+)\d(\w+)/; print "var1: $1\tvar2: $2\n"; my $p = "$2$1"; # works and prints "p is barfoo" # call script as "perl pmtest.pl $2$1" #my $p = "$ARGV[0]"; # doesn't work, prints "p is $2$1" print "p is $p\n";
Results when hardcoded into script:
var1: foo var2: bar p is barfoo
Results when using ARGV[0] method as "perl pmtest.pl $2$1":
var1: foo var2: bar p is $2$1
Here is another conceptual version illustrating the issue we've run into.
use strict; use warnings; use Config::IniFiles; my %args; my $global_ini_data = Config::IniFiles->new( -file => "test.ini" ); my $regex = $global_ini_data->val( 'client1', 'rename' ); my $filename = "201306051200foobar.dat"; print "REGEX: $regex\n"; print "BEFORE: $filename\n"; # Uncomment each method individually to test # Method 1: doesn't work #$filename =~ qr($regex); # Method 2: doesn't work #$filename =~ $regex ; # Method 3: doesn't work #$filename = modify($filename, sub { $_[0] =~ $regex }); # Method 4: doesn't work (not global) #my ($before, $after) = $regex =~ m{/(.*)/(.*)/}; #$filename = replace($filename, $before, sub { $after }, 0); # Method 5: doesn't work (global) #my ($before, $after) = $regex =~ m{/(.*)/(.*)/}; #$filename = replace($filename, $before, sub { $after }, 1); # Method 6: works, but hardcoded and not in INI; not scalable $filename =~ s/(\d{2})(\d{2})(\d{4})(.*)/$3$2\.$4/; # End Methods test print "AFTER: $filename\n"; exit; sub replace { my($string, $find, $replace, $global) = @_; unless($global) { $string =~ s($find){ $replace->() }e; } else { $string =~ s($find){ $replace->() }ge; } return $string; } sub modify { my($text, $code) = @_; $code->($text); return $text; }
The test.ini config file
[client1] # PURPOSE: Convert YYYYMMDDhhmmss to MMDDYY.hhmmss rename=s/(\d{2})(\d{2})(\d{4})(.*)/$3$2\.$4/
The results: Methods 1 - 3 (not working)
BEFORE: 201306051200foobar.dat AFTER: 201306051200foobar.dat
Methods 4 - 5 (not working)
BEFORE: 201306051200foobar.dat AFTER: $3$2\.$4
Method 6 works, but hardcoded:
BEFORE: 201306051200foobar.dat AFTER: 060513.1200foobar.dat

Any ideas to make capture groups work when patterns defined in INI?

NOTE:

(1) I know the test.ini format leaves security risk of code injection--the above script is just for illustrative purposes. In the prod script, we actually just parse the before and after regex patterns from the INI and build the correct substitution regex.

(2) I consulted these posts, which provided valuable insight (and used in above methods) and ALMOST have the solution, but either don't work for capture groups defined in INI or when it does work, it's too rigid by hardcoding the number of capture groups in source code rather than allowing it to be dynamically defined in an INI, again necessary because we may potentially be holding hundreds of unique client configurations and need this to scale:


In reply to Interpolation of capture buffers not working when regex stored in variable by jacklh

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.