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

Hi all, I have a file, the contents are:
@a = ("'hello world'",'print ', ';'); eval(@a[1] . @a[0] . @a[2]);
what i'm trying to do is read the file and replace the array index numbers with random numbers, so far here is what i've come up with:
$re='.*?(@)((?:[a-z][a-z0-9_]*))(\\[)(\\d+)(\\])'; open(FILE, "+<ibank.txt"); @code = <FILE>; close FILE; foreach (@code) { $code .= $_; if ($_ =~ m/$re/) { $rndIndex=0; $c1=$1;$var1=$2;$index=$4;$c3=$5; $rndIndex = int(rand(99999)); $old = $c1.$var1.$index.$c3; $varName = "$index$c3"; $varName =~ s/$index/$rndIndex/; $code =~ s/[$old]/$varName/g; } } print $code; #show output example
the problem is this only replaces the first array found "@a1" the others and untouched.. why is this? :/ thanks

Replies are listed 'Best First'.
Re: Replace arrays in external file
by CountZero (Bishop) on Apr 10, 2012 at 15:30 UTC
    And you probably meant eval($a[1] . $a[0] . $a[2]); rather than eval(@a[1] . @a[0] . @a[2]);

    Or use eval("$a[1]$a[0]$a[2]"); It will save you a few keystrokes.

    Your program then can become:

    use Modern::Perl; while (<DATA>) { do {print; next} unless /^eval/; s/(?<=\[)\d+(?=])/int(rand(99999))/ge; print; } __DATA__ @a = ("'hello world'",'print ', ';'); eval("$a[1]$a[0]$a[2]");

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
      i may have forgotten to mention that the array indexes must match, lets say @a1 was changed to "@a3455" all @a1's should be changed to match that one. my original code doesnt like those dots in the eval statement.
        I showed you an alternative way of writing your eval which does not need any "dots".

        To make the "random" values stick to the elements of the @a array, try this:

        use Modern::Perl; my @replace = map int(rand(99999)), (0 .. 10); while (<DATA>) { do {print; next} unless /^eval/; s/(?<=\[)(\d+)(?=])/$replace[$1]/ge; print; } __DATA__ @a = ("'hello world'",'print ', ';'); eval("$a[1]$a[0]$a[2]");

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        My blog: Imperial Deltronics
Re: Replace arrays in external file
by brx (Pilgrim) on Apr 10, 2012 at 14:54 UTC

    You have to replace:  if (/$re/) {...}

    with :  while (/$re/g) {...}

    -----
    use strict; my $re='.*?(@)((?:[a-z][a-z0-9_]*))(\\[)(\\d+)(\\])'; my @code = <DATA>; my $code; foreach (@code) { $code .= $_; while (/$re/g) { my $rndIndex; my $c1=$1;my $var1=$2;my $index=$4;my $c3=$5; $rndIndex = int(rand(99999)); my $old = $c1.$var1.$index.$c3; my $varName = $index.$c3; $varName =~ s/$index/$rndIndex/; $code =~ s/[$old]/$varName/g; } } print $code; #show output example __DATA__ @a = ("'hello world'",'print ', ';'); eval(@a[1] . @a[0] . @a[2]);

    Update: You don't have to capture "@", "[", "]"... plus several simplifications.

    use strict; my $code; { #slurp mode (http://perldoc.perl.org/perlvar.html) local $/; $code = <DATA>; } my $re = qr {\@([a-z][a-z0-9_]*)\[\d+]}; $code =~ s{$re}{ "\@$1\[" . int(rand(99999)) . "]" }eg; print $code; #show output example __DATA__ @a = ("'hello world'",'print ', ';'); eval(@a[1] . @a[0] . @a[2]);