Abhishek Kulkarni
Abhishek Kulkarni

Reputation: 3818

String substitution doesn't work in perl

Given text is the 'C' style structure -

    struct mystruct {
        int a[100];
        int b[10*10];
        int c[10*5+(25*2)];
        int d[10^2];
    }

Read the text line by line and evaluate the number of elements in each array and re-declare arrays with element count.

Result should be printed as follows :-

    struct mystruct {
        int a[100];
        int b[100];
        int c[100];
        int d[100];
    }

Following string substitution doesn't work for me -

    if ($line =~ m/.*?\[(.*?)\]/) {
        $answer = eval ($1);
        $line =~ s/$1/$answer/g;
    }

The substitution did not work and the $line remained unchanged for all evaluated element count.

Upvotes: 0

Views: 182

Answers (4)

Diab Jerius
Diab Jerius

Reputation: 2320

Use quotemeta to sanitize your replacement string:

if ( $line =~ m/.*?\[(.*?)\]/ ) {
    my $expr = quotemeta($1);
    my $answer = eval ($1);
    $line =~ s/$expr/$answer/;
}

Upvotes: 0

swafo
swafo

Reputation: 25

Looks like Miguel is right:

my $string =
q|int a[100];
int b[10*10];
int c[10*5+(25*2)];
int d[10^2];|;

foreach my $line (split(/\n/,$string)) {
        if ($line =~ m/\[([^\]]+)\]/) {
                my $equation = $1;
                my $val = eval($equation);
                # escape out the special characters.
                $equation =~ s/\*/\\\*/g;
                $equation =~ s/\,/\\\,/g;
                $equation =~ s/\+/\\\+/g;
                $equation =~ s/\)/\\\)/g;
                $equation =~ s/\(/\\\(/g;
                $equation =~ s/\^/\\\^/g;

                $line =~ s/\[$equation\]/\[$val\]/;
        }
        print "$line\n";
}

This returns:

int a[100];
int b[100];
int c[100];
int d[8];

So you see you'll also need to alter the special character for "power of". But I think this points you in the right direction.

Upvotes: 0

TLP
TLP

Reputation: 67900

Do the evaluation directly in the substitution:

$line =~ s/(?<=\[)   # assert a square bracket behind
           ([^]]*)   # capture string of non-brackets
           (?=\])    # assert square bracket after
          /$1/eex;   # double evaluate the variable

The double evaluation is necessary, as the first evaluation turns the variable into a string, and then the string is evaluated.

Although you will run into trouble with 10^2, as ^ is the binary XOR operator, not the exponentiation operator **.

Upvotes: 5

pstr
pstr

Reputation: 384

Try this way: $line =~ s/.*?\[(.*?)\]/$1/ge

Upvotes: 0

Related Questions