why not just eval?
Because with eval, you must worry about delimiters. For example, if either string had contained "/", the eval example given elsewhere in this thread would fail. Also, eval invites disaster in a proxy-privilege environment (like CGI or other daemons).
The lookup table isn't hard to create:
## initialization
my $old = 'abc';
my $new = 'xyz';
my %table; @table{split //, $old} = split //, $new;
my $table_re = join '|', map quotemeta reverse sort keys %table;
## the deed
my $string = 'abracadabra';
$string =~ s/($table_re)/$table{$1}/g;