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

sorry for double post, i think the code explains with the comments what im trying to do :)
$re='.*?(@)((?:[a-z][a-z0-9_]*))(\\[)(\\d+)(\\])'; #find arrays e.g: @ +arry[123] open(FILE, "+<", "xxxxx.pl"); @code = <FILE>; close FILE; $code = join ("",@code); foreach (@code) { if($_ =~ m/$re/) { #check if this line contains any array my $random_number = int(rand(9999)); #create a new index +for that array $OldVariable = $1.$2.$3.$4.$5; #store the old array + in variable $NewVariable = $1.$2.$3.$random_number.$5; #changing the index +in the found array $code =~ s/$OldVariable/$NewVariable/g; #now replace all of +that found array with the new one. } } print $code; <>;
all of the arrays matching the exact one found should be replaced, eg: @array123 @array123 @array1234 @array1234 could be: @array6677 @array6677 @array8686 @array8686 thanks!

Replies are listed 'Best First'.
Re: Same problem replacing array index numbers
by JavaFan (Canon) on Apr 11, 2012 at 14:49 UTC
    Multiple problems here.
    1. $OldVariable contains characters special to the regexp engine -- prepend with \Q.
    2. The random number may be repeated.
    3. Once you've modified $code, @code isn't updated.
    4. Your code doesn't deal with multiple arrays on a line.
    5. The sigil for (scalar) array access is $, not @.
    6. You aren't modifying any arrays that aren't indexed (for instance, your code leaves my @array untouched).
    7. You're assuming there's no space between the array name and the index.
    8. You're assuming the index consists of just a number, what if it's an expression, a variable, or has whitespace?
    9. You're missing all the arrays containing capital letters, or that start with an underscore.
      i'm aware of some of these problem thats where i need help :) all of the assumptions are people i will be the person who makes the files that are to be modified its for personal use.:) thanks
Re: Same problem replacing array index numbers
by AnomalousMonk (Archbishop) on Apr 11, 2012 at 15:45 UTC

    Reading your 'duplicate' post, I'm not quite sure what you are trying to achieve there. As to this post, the example below may be of interest. I think it should be suitable for either line-by-line or whole-file processing. 5.10+ needed due to use of  \K operator.

    BTW: In addition to the problems with the code in this post pointed out by JavaFan, I would add that  int rand 9999 will only produce numbers in the range 0 .. 9998. I don't know if this was intended or not.

    >perl -wMstrict -le "my $s = 'xx @ra[1] y @ara[23] z @ra[1] aa @ara[23] b @ra[1] @ara[23]'; print qq{'$s'}; ;; my %found; $s =~ s{ \@ ([a-z] [a-z\d_]* \[) \K (\d+) (?= \]) } { $found{$1 . $2} //= int rand 9999; }xmsge; print qq{'$s'}; " 'xx @ra[1] y @ara[23] z @ra[1] aa @ara[23] b @ra[1] @ara[23]' 'xx @ra[2038] y @ara[6310] z @ra[2038] aa @ara[6310] b @ra[2038] @ara[ +6310]'

    Update: Used  //= instead of  ||= in substitution replacement block code per Anonymonk's usage below.

      Please let me to improve your code:
      my $s = 'xx @ra[1] y @ara[23] z @ra[1] aa @ara[23] b @ra[1] @ara[23]'; print qq{'$s'\n}; my %found; my %generated; $s =~ s{ \@ ([a-z] [a-z\d_]* \[) \K (\d+) (?= \]) } { $found{"$1$2"} //= do { my $rand; do {$rand = int rand 9999} while exists $generated{$rand}; $generated{$rand} = (); $rand; }; }xmsge; print qq{'$s'\n};
      Fixed issues of producing something like this:
      'xx @ra[1] y @ara[23] z @ra[1] aa @ara[23] b @ra[1] @ara[23]' 'xx @ra[1] y @ara[0] z @ra[1] aa @ara[2] b @ra[1] @ara[2]'
        ... producing something like this:
        'xx @ra[1] y @ara[23] z @ra[1] aa @ara[23] b @ra[1] @ara[23]'
        'xx @ra[1] y@ara[0] z @ra[1] aa@ara[2] b @ra[1] @ara[2]'

        Good catch on the use of  //= versus  ||= in your code since the value of the generated random integer could, indeed, be zero leading to a redefinition on a subsequent encounter. I would quibble with
            $generated{$rand} = ();
        however, since assigning the contents of an empty list to a scalar (i.e., undef) is very odd and likely to be confusing, it is much better, IMO, to assign 1 (or any true value) since that would slightly simplify the existence test to
            do { ... } while $generated{$rand};
        (if, in fact, there is a requirement that the generated random integers be non-repeating).

        ow.. cool.. could i also use a modified version of that to replace the array names to like a random string? i tried it myself but i cant replace with a string, only numbers...