我不明白Perl中的自动增量字母。
这个例子似乎完全可以理解:
$a = 'bz'; ++$a;
ca #output
b
会增加到c
。 z
没有任何内容可以转到a
(或至少这是我看到的过程)。
但后来我遇到了这样的陈述:
$a = 'Zz'; ++$a;
AAa #output
和
$a = '9z'; ++$a;
10 #output
为什么不递增Zz
返回Aa
?为什么不递增9z
返回0z
?
谢谢!
答案 0 :(得分:23)
引用perlop:
但是,如果变量已经存在 因为它只用在字符串上下文中 已设置,并且值不是 空字符串并匹配 模式
/^[a-zA-Z]*[0-9]*\z/
, 增量以字符串形式完成, 保留其中的每个角色 范围,携带。
范围是0-9,A-Z和a-z。当需要新角色时,它取自第一个角色的范围。每个范围都是独立的;角色永远不会离开他们开始的范围。
9z
与模式不匹配,因此它获得了数字增量。 (它可能应该给出“参数不是数字”警告,但它不在Perl 5.10.1中。)数字只允许之后所有字母(如果有的话),从来没有它们。
请注意,全数字字符串 与模式匹配, 接收字符串增量(如果它从未在数字上下文中使用过)。但是,此类字符串上的字符串增量结果与数字增量相同,只是它具有无限精度并保留前导零(如果有)。 (因此,当数字位数超过IV或NV可以存储的位数或者它具有前导零时,您只能说出区别。)
我不明白为什么你认为Zz
应该成为Aa
(除非你考虑使用模运算,但事实并非如此)。通过此过程变为AAa
:
z
增加到a
。增加前一个字符。Z
增加到A
。之前没有字符,因此请添加此范围中的第一个字符,即另一个A
。 range operator(..
),当给出两个字符串(并且左边的一个匹配模式)时,使用字符串增量来生成一个列表(这在附近的结尾处解释)部分)。该列表以左侧操作数开始,然后递增,直到:
它返回所有值的列表。 (如果案例2终止了列表,则最终值不包含在其中。)
答案 1 :(得分:6)
因为(暂时忽略案例;案件只是保留,没有任何有趣的事情发生),'AA'是'Z'的继承者,那么它怎么也可能成为'ZZ'的继承者呢? 'ZZ'的继任者是'AAA'。
因为就++
和所有其他数字运算符而言,"9z"
只是编写9的愚蠢方式,而9的后继是10.特殊的字符串行为自动增量明确指定仅发生在字母串或字母串后跟数字(而不是以任何其他方式混合)。
答案 2 :(得分:3)
答案是不这样做。 ++
与非数字的自动递增充满了令人讨厌的陷阱。它仅适用于快速黑客攻击。
你最好为这类事情编写自己的迭代器:
#!/usr/bin/perl
use strict;
use warnings;
{ package StringIter;
sub new {
my $class = shift;
my %self = @_;
$self{set} = ["a" .. "z"] unless exists $self{set};
$self{value} = -1 unless exists $self{value};
$self{size} = @{$self{set}};
return bless \%self, $class;
}
sub increment {
my $self = shift;
$self->{value}++;
}
sub current {
my $self = shift;
my $n = $self->{value};
my $size = $self->{size};
my $s = "";
while ($n >= $size) {
my $offset = $n % $size;
$s = $self->{set}[$offset] . $s;
$n /= $size;
}
$s = $self->{set}[$n] . $s;
return $s;
}
sub next {
my $self = shift;
$self->increment;
return $self->current;
}
}
{
my $iter = StringIter->new;
for (1 .. 100) {
print $iter->next, "\n";
}
}
{
my $iter = StringIter->new(set => [0, 1]);
for (1 .. 7) {
print $iter->next, "\n";
}
}
答案 3 :(得分:2)
你在问为什么增量不会消失。
如果确实如此,它实际上并不是一个增量。增加意味着你有一个完全有序的集合和一个元素,并产生下一个更高的元素,所以它永远不会让你回到较低的元素。在这种情况下,总排序是字符串的标准字母顺序(仅在英文字母表中定义),扩展为以某种常见类型的标识符字符串看似自然的方式处理任意ASCII字符串。
包装也会破坏它的目的:通常你想用它来生成任意多种不同的标识符。
我同意Chas Owens的判决:将此操作应用于任意字符串是一个坏主意,这不是它的用途。
我不同意他的补救措施:只需选择一个简单的起始值,其中增量表现得非常好,你会没事的。
答案 4 :(得分:0)
我不明白为什么递增Zz会返回Aa;为什么你认为它应该? 9z递增看起来像Perl认为9z是9号而不是某种基础36怪异。
答案 5 :(得分:-1)
=>如果字母数字字符串以'bz'或'Zz'之类的字符开头,则从右开始移动。第一个字符为'z'如您所说,'z'无处可递增因此它增加到'a',但是额外的进位被赋予左边的下一个数字。因此'b'增加到'c'。现在在第二种情况下,Z看不到它的左侧的任何字母。在这种情况下,当数字递增时会创建当前数字的额外副本。
=>对于以'9z'这样的数字开头的字母数字字符串,perl会将其视为用户的错误,并将其视为字符串前面的数字(在这种情况下为9),并递增数。所以9变成10。
Plz。如果我错了请纠正我