Tr Perl /// не делает то, что я хочу - PullRequest
2 голосов
/ 01 августа 2010

EDIT: 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/// удалил символы из @invalid через map ... Где я ошибся? (кстати, с помощью регулярных выражений это работает).

Ответы [ 3 ]

7 голосов
/ 01 августа 2010

Функция tr в Perl не поддерживает переменные .

Обратите внимание, что поскольку таблица перевода создается во время компиляции, ни SEARCHLIST, ни REPLACEMENTLIST не подвергаютсядвойная кавычка интерполяция.Это означает, что если вы хотите использовать переменные, вы должны использовать eval ():

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

(Источник)

4 голосов
/ 01 августа 2010

Поскольку 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
2 голосов
/ 01 августа 2010

Чтобы удалить с помощью tr, вам нужно указать флаг / d.В противном случае он по умолчанию устанавливает список замен на основе списка поиска (поэтому просто считает или сжимает).

И tr не поддерживает переменную интерполяцию.

Чтобы использовать tr, вам нужно сделать что-то вродеэто:

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

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

    return $str;
}
...