Perl's tr/// is not doing what I want

隐身守侯 提交于 2019-12-08 03:30:21

问题


EDIT: tr/// does not support variable interpolation, so I went with s/\Q$_\E//g; instead

Or, more likely, I'm not doing something right...

I have the following code:

#!/usr/bin/perl

use strict;
use warnings;
use utf8;

sub strip_invalid {
  my ($str, @chars) = @_;

  map { $str =~ tr/$_//; } @chars;

  return $str;
}

my @invalid = qw( a e i o u );

print strip_invalid("This is the super sample with vowels.\n", @invalid);

I'd just like to pass a string to strip_invalid() and have tr/// remove the characters in @invalid through a map... Where did I go wrong? (by the way, using regular expressions it works).


回答1:


Perl's tr feature doesn't support variables.

Note that because the translation table is built at compile time, neither the SEARCHLIST nor the REPLACEMENTLIST are subjected to double quote interpolation. That means that if you want to use variables, you must use an eval():

eval "tr/$oldlist/$newlist/";

(Source)




回答2:


Since tr/// does not allow the use of variables, I would suggest something along these lines (rather than using eval, which raises other concerns):

sub strip_invalid {
    my $str = shift;
    my $chars = quotemeta(join '', @_);
    $str =~ s/[$chars]//g;
    return $str;
}

Note also that tr/// has a delete option, so it's not necessary to iterate across all characters that you want to delete. For example:

$str =~ tr/aeiou//d; # Delete all vowels from $str



回答3:


To delete with tr, you need to specify the /d flag. Otherwise, it defaults the replacementlist based on the searchlist (so just counts or compresses).

And tr does not support variable interpolation.

To use tr, you'd need to do something like this:

sub strip_invalid {
    my ($str, @chars) = @_;

    my $strip = quotemeta join '', @chars;
    eval "\$str =~ tr/$strip//d";

    return $str;
}


来源:https://stackoverflow.com/questions/3382657/perls-tr-is-not-doing-what-i-want

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!