in reply to Re^2: Transform ASCII into UniCode (escape_metas)
in thread Transform ASCII into UniCode

I'm probably too busy today to understand. We wanted to escape the strings so they can be used in a transliteration, right? Why not test it directly, then?
sub use_it { my ($string, $search, $replace) = @_; my ($s, $r); $s = escape_metas('/', '\\') for $search; $r = escape_metas('/', '\\') for $replace; return eval "\$string =~ tr/$s/$r/r" } sub cheat { my ($string, $search, $replace) = @_; return eval "\$string =~ tr|\Q$search\E|\Q$replace\E|r" } sub simulate { my ($string, $search, $replace) = @_; my $result = $string; for my $i (0 .. length($search) - 1) { my $from = substr $search, $i, 1; my $to = substr $replace, $i, 1; $result =~ s/\Q$from/$to/g; } return $result } for my $case ( # String search replace expect ['a/b' => 'a/b', 'xyz', 'xyz'], ['a\\b' => 'a\\b', 'xyz', 'xyz'], ['a/b' => '\\/', 'xy', 'ayb'], ['a\\/b' => '\\/', 'xy', 'axyb'], ['a/\\b' => '\\/', 'xy', 'ayxb'], ['a\\\\b' => '\\/', 'xy', 'axxb'], ['a\\\\/b' => '\\/', 'xy', 'axxyb'], ) { is simulate(@$case), $case->[-1], 'simulate'; is cheat(@$case), simulate(@$case), 'cheat'; is use_it(@$case), simulate(@$case), 'use'; }
I'm not sure I got the "expect" right, but both "simulate" and "cheat" give the same results. "use", on the other hand, doesn't. I based it on your escape_metas - what did I do wrong?

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^4: Transform ASCII into UniCode (escape_metas)
by LanX (Saint) on Mar 23, 2021 at 18:18 UTC
    > Why not test it directly, then?

    I wanted to have a generic method for escaping selected metas while keeping others as is.

    > what did I do wrong?

    Took me a moment to understand (well guess) what's happening

    Take case #2:

    a\\b is internally the 3 char string a\b , so this escape b is untouched.

    but you do a string interpolation for

    eval "\$string =~ tr/$s/$r/r"

    so whats happening is

    DB<57> say "a\\b" =~ tr/a\b/xyz/r # expected 'xyz' x\b DB<58>

    Actually I'm not sure what tr's interpretation of \b is here

    Question is if your expectation was right, because the literal code gives my result (?)

    C:\tmp\t_wperl>perl -E"say 'a\\b' =~ tr/a\b/xyz/r # expected 'xyz'" x\b C:\tmp\t_wperl>

    update

    I.o.W.

    Your expectation is to have a 1-to-1 mapping of characters.

    My expectation was to emulate tr like implemented and to catch injections.

    It's a question of definition.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

        I see. I would expect the strings coming in to contain the characters to operate on, not strings that Perl can turn into the characters to operate on by evaluating them.

        The \b is tricky, as I can use it to get three different results from my three subroutines:

        # Add this to the list of cases: [ "a\b\\b" => '\\/', 'xy', "a\bxb"] # Results: not ok 22 - simulate # Failed test 'simulate' # at ./2.pl line 64. # got: 'xb' # expected: 'xb' ok 23 - cheat Replacement list is longer than search list at (eval 45) line 1. not ok 24 - use # Failed test 'use' # at ./2.pl line 66. # got: '\b' # expected: 'xb'

        Switching to Test2::V0 explains the test 22:

        not ok 22 - simulate # Failed test 'simulate' # at ./2.pl line 64. # +-------+----+-------+ # | GOT | OP | CHECK | # +-------+----+-------+ # | a\bxb | eq | xb | # +-------+----+-------+

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]