Search code examples
regexfunctionperl

Perl to call the tr function in regex replace


How to properly use the tr result in regex replace?

echo 'E2"C"G | d3"G7" | F3"F" | A3"Dm" ' | perl -pe 's{".*?"}{$& =~ tr [\000-\177][\200-\377]r}ge;'

This works expectedly, however, when I tried to make use of the tr result to construct what I want,

echo 'E2"C"G | d3"G7" | F3"F" | A3"Dm" ' | perl -pe 's{".*?"}{$& =~ tr [\000-\177][\200-\377]r; " %$&% ";}ge;'

Things start to fall apart (the 8bit-set string is gone).
How to fix it please? (I tried to assign $& to a variable $m and use $m instead, but that didn't solve the problem)


Solution

  • The $& variable is read-only so the tr operator cannot change it, which is why you use tr on it with /r modifier -- Then it returns the changed string (or the unchanged original if there were no changes) and leaves the original intact.

    So assign that return to a variable and then use that variable

    s{...}{ my $new = $& =~ tr[...][...]r; " %$new% " }
    

    ($new may be same as old, $&)   or compose your needed expression directly

    s{...}{ " %" . $& =~ tr[...][...]r . "% " }
    

    Given the parenthetical remark in the question

    (I tried to assign $& to a variable $m and use $m instead, but that didn't solve the problem)

    yet another way is to first copy $& into a variable and then do as you please with it

    {...}{ my $m = $&; $m =~ tr[...][...]; " %$m% " }
    

    Note that now we don't want the /r modifier since that $m should be changed in-place (what wouldn't happen with /r)