1

我正在查看其他人编写的 Perl 脚本,我发现了这一点:

$num2 = '000000';
substr($num2, length($num2)-length($num), length($num)) = $num;
my $id_string = $text."_".$num2

请原谅我的无知,但是对于未经培训的 Perl 程序员来说,第二行看起来好像作者正在将字符串分配给$numfunction 的结果substr。这条线到底是做什么的?

4

4 回答 4

6

正是你认为它会做的:

$ perldoc -f substr

您可以将 substr() 函数用作左值,在这种情况下,EXPR 本身必须是左值。如果你分配的东西比 LENGTH 短,字符串会缩小,如果你分配的东西比 LENGTH 长,字符串会增长以适应它。为了使字符串保持相同的长度,您可能需要使用“sprintf”填充或截断您的值。

于 2012-09-10T19:52:24.897 回答
4

在 Perl 中(与 Python 不同,其中字符串、元组不能就地修改),字符串可以就地修改。这就是substr这里所做的,它只修改字符串的一部分。您可以使用更神秘的语法来代替这种语法:

substr($num2, length($num2)-length($num), length($num),$num);

它完成了同样的事情。您可以进一步拉伸它。想象一下,您想用bar替换字符串中的所有foo实例,但仅限于前 50 个字符内。Perl 将让您以单行方式完成:

substr($target,0,50) =~ s/foo/bar/g;

太好了,不是吗?

于 2012-09-10T19:58:30.277 回答
2

“确切地”,你问?

通常,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
'
于 2012-09-10T22:00:53.630 回答
1

在我看来,它正在用 $num 的内容覆盖 $num2 的最后一个 length($num) 个字符,以获得一个填充为“0”的数字。

我想大多数人会用 sprintf() 完成同样的任务

于 2012-09-10T19:55:51.180 回答