【问题标题】:Perl's tr/// is not doing what I wantPerl 的 tr/// 没有做我想做的事
【发布时间】:2010-08-02 02:39:39
【问题描述】:

编辑:tr/// 不支持变量插值,所以我改用s/\Q$_\E//g;

或者,更有可能的是,我做的不对……

我有以下代码:

#!/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);

我只想将一个字符串传递给strip_invalid() 并让tr/// 通过map 删除@invalid 中的字符...我哪里出错了? (顺便说一句,它可以使用正则表达式)。

【问题讨论】:

    标签: perl functional-programming map transliteration


    【解决方案1】:

    Perl 的tr 功能doesn't support variables

    请注意,因为转换表是在编译时构建的,所以 SEARCHLIST 和 REPLACEMENTLIST 都不受双引号插值的影响。这意味着如果要使用变量,则必须使用 eval():

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

    (Source)

    【讨论】:

      【解决方案2】:

      由于tr/// 不允许使用变量,我建议按照这些思路(而不是使用eval,这会引起其他问题):

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

      还要注意tr/// 有一个删除选项,因此没有必要遍历所有要删除的字符。例如:

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

      【讨论】:

        【解决方案3】:

        要使用 tr 删除,您需要指定 /d 标志。否则,它会根据搜索列表默认替换列表(因此只是计数或压缩)。

        而且tr不支持变量插值。

        要使用 tr,您需要执行以下操作:

        sub strip_invalid {
            my ($str, @chars) = @_;
        
            my $strip = quotemeta join '', @chars;
            eval "\$str =~ tr/$strip//d";
        
            return $str;
        }
        

        【讨论】:

          猜你喜欢
          • 2014-07-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-22
          • 2015-11-13
          • 2020-11-26
          • 2011-03-28
          相关资源
          最近更新 更多