4

这是一个愚蠢的问题;我需要这个来处理更复杂的事情,但让我们让它变得简单:

$i = quotemeta 'A';
$line =~ tr/a-z/$i-Z/;

这是一个愚蠢的替换,这应该将小写字母变成大写字母,但是我尝试过的方法都行不通。

好的,所以我看到这带来了很多混乱,真正的代码应该是:

$line =~ tr/A-Z/F-ZA-E/;

它应该是一个 Caesers Chiper 算法。如果您想通过固定数量的字母更改它,这很好用,但我需要一个变量,所以我可以根据需要更改任意数量的字母。但我想运送 eval Thnx

PS 另外,为什么 s/// 不适用于范围?

4

4 回答 4

4

如果你真的需要 tr,你可以使用 eval:

$i = quotemeta 'A'
eval("\$line =~ tr/a-z/$i-Z/;");
于 2012-05-02T23:56:51.043 回答
4

请注意tr///,您只能使用文字字符,而不能使用变量。所以,tr/a-z/$i-Z/不起作用,你必须使用tr/a-z/A-Z/. 在perldoc perlop 中,您可以阅读更多关于tr///插值或缺少插值的解释。

将字符串转换为大写,尽管还有其他方法。您可以使用该uc函数或正则表达式转义序列\U(大写)和\L(小写)。例如:

my $str = 'a';
my $uppercase = uc $str;

正则表达式:

my $str = 'abcdef';
$str =~ s/([a-z]+)/\U$1/;  # $str is now 'ABCDEF'

tchrist 指出[a-z]应该写\p{CWU},这将包括所有受大小写影响的字符。

更新:

如果您正在尝试创建某种动态编码功能,我建议使用一个子程序来获取参数,并手动移动字符。

sub foo {
    my ($str, $num) = @_;  # num is how many characters to shift the alphabet
    my @in  = 'A' .. 'Z';
    my @out = @in[$num .. $#in, 0 .. $num-1];
    my %out = map { $in[$_] => $out[$_] } 0 .. $#in;
    $str =~ s#(.)# $out{$1} // $1 #eg;  # if key does not exist, use org
    return $str;
}

请注意,它区分大小写,但您可以添加小写键来解决此问题。

于 2012-05-02T23:51:20.707 回答
2

不幸的是,你的例子不是一个好例子;操作员tr不接受任何变量插值(在任何一半)。如果您实际使用tr,除非您使用 ,否则您将不走运eval,不建议这样做。如果您不使用tr,请向我们展示实际代码,以便我们了解发生了什么并提供更多建议。

更新

这个怎么样?

my %map;
@map{'A'..'Z'} = ('F'..'Z','A'..'E');
s/[A-Z]/$map{$&}/g;

不确定它是否仍然正确,但曾几何时,$&由于可怕的性能损失,要不惜一切代价避免。你可以很容易地做到这一点:

s/([A-Z])/$map{$1}/g;
于 2012-05-02T23:56:11.277 回答
0

tr 不适用于变量;改用 s/// (替换)。

于 2012-05-02T23:51:43.820 回答