我正在查看其他人编写的 Perl 脚本,我发现了这一点:
$num2 = '000000';
substr($num2, length($num2)-length($num), length($num)) = $num;
my $id_string = $text."_".$num2
请原谅我的无知,但是对于未经培训的 Perl 程序员来说,第二行看起来好像作者正在将字符串分配给$num
function 的结果substr
。这条线到底是做什么的?
正是你认为它会做的:
$ perldoc -f substr
您可以将 substr() 函数用作左值,在这种情况下,EXPR 本身必须是左值。如果你分配的东西比 LENGTH 短,字符串会缩小,如果你分配的东西比 LENGTH 长,字符串会增长以适应它。为了使字符串保持相同的长度,您可能需要使用“sprintf”填充或截断您的值。
在 Perl 中(与 Python 不同,其中字符串、元组不能就地修改),字符串可以就地修改。这就是substr
这里所做的,它只修改字符串的一部分。您可以使用更神秘的语法来代替这种语法:
substr($num2, length($num2)-length($num), length($num),$num);
它完成了同样的事情。您可以进一步拉伸它。想象一下,您想用bar替换字符串中的所有foo实例,但仅限于前 50 个字符内。Perl 将让您以单行方式完成:
substr($target,0,50) =~ s/foo/bar/g;
太好了,不是吗?
“确切地”,你问?
通常,substr
返回一个无聊的字符串(PV 和 POK)。
$ perl -MDevel::Peek -e'$_="abcd"; Dump("".substr($_, 1, 2));'
SV = PV(0x99f2828) at 0x9a0de38
REFCNT = 1
FLAGS = (PADTMP,POK,pPOK)
PV = 0x9a12510 "bc"\0
CUR = 2
LEN = 12
但是,当substr
在期望左值(可分配值)的地方进行评估时,它会返回一个神奇的标量(PVLV 与 GMG(获取魔法)和 SMG(设置魔法))。
$ perl -MDevel::Peek -e'$_="abcd"; Dump(substr($_, 1, 2));'
SV = PVLV(0x8941b90) at 0x891f7d0
REFCNT = 1
FLAGS = (TEMP,GMG,SMG)
IV = 0
NV = 0
PV = 0
MAGIC = 0x8944900
MG_VIRTUAL = &PL_vtbl_substr
MG_TYPE = PERL_MAGIC_substr(x)
TYPE = x
TARGOFF = 1
TARGLEN = 2
TARG = 0x8948c18
FLAGS = 0
SV = PV(0x891d798) at 0x8948c18
REFCNT = 2
FLAGS = (POK,pPOK)
PV = 0x89340e0 "abcd"\0
CUR = 4
LEN = 12
这个神奇的标量保存传递给susbtr
(TARG、TARGOFF 和 TARGLEN)的参数。您可以看到由TARG
(传递给的原始标量substr
)指向的标量在末尾重复(您在底部看到的 0x8948c18 处的 SV)。
对这个神奇的标量的任何读取都会导致调用关联的函数。同样,写入调用不同的关联函数。substr
这些函数会导致读取或修改传递给的字符串的选定部分。
perl -E'
$_ = "abcde";
my $ref = \substr($_, 1, 3); # $$ref is magical
say $$ref; # bcd
$$ref = '123';
say $_; # a123e
'
在我看来,它正在用 $num 的内容覆盖 $num2 的最后一个 length($num) 个字符,以获得一个填充为“0”的数字。
我想大多数人会用 sprintf() 完成同样的任务