Home > other >  perl regex error: Modification of a read-only value attempted
perl regex error: Modification of a read-only value attempted

Time:08-26

I have this perl script:

use strict;
use warnings;

foreach my $line (" ^?[?12;12A", " ^?[A") {
    print "$line\n";
    $line =~ s/\s?[[:cntrl:]]\[(\?)?([0-9]{1,2}(;[0-9]{1,2})?)?[a-zA-Z]//g;
    print "$line\n";

}

Those are two strings that start with a space, then a control character, then some regular ascii characters. It results with this error:

$ perl foo.pl
 [?12;12A
Modification of a read-only value attempted at foo.pl line 6.
$

What am I doing wrong?

CodePudding user response:

In your case $line is a read-only value.

You can fix this in two ways:

  1. Work with an actual array like my @testarray = (" ^?[?12;12A", " ^?[A");

  2. Assign the value of $line to another variable and modify that:

    my $tmp = $line; 
    $tmp =~ s/\s?[[:cntrl:]]\[(\?)?([0-9]{1,2}(;[0-9]{1,2})?)?[a-zA-Z]//g;
    

CodePudding user response:

In a foreach loop the loop variable ("topicalizer") is but an alias for the currently processed list element; by changing it we really change the element.

If any element of LIST is an lvalue, you can modify it by modifying VAR inside the loop. Conversely, if any element of LIST is NOT an lvalue, any attempt to modify that element will fail. In other words, the foreach loop index variable is an implicit alias for each item in the list that you're looping over.

The loop in the question iterates over a list of string literals, and those are read-only.

Some ways around this are given in Hameed's answer, to store them in an array first or assign to a temporary variable. Or use the "non-destructive" modifier on the substitution operator, s/.../.../r, which doesn't change the original but returns the changed value (or the original if it didn't change).

  • Related