繁体   English   中英

将字符串分配给Perl substr?

[英]Assigning a string to Perl substr?

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

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

原谅我的无知,但是对于未经培训的Perl程序员,第二行看起来好像作者正在将字符串$num分配给函数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返回一个无聊的字符串(带有POK的PV)。

$ 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求值时,它将返回一个神奇的标量(带有GMG(获取魔法)和SMG(设置魔法)的PVLV)。

$ 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的原始标量)(在底部看到的SV在0x8948c18处)。

对该神奇标量的任何读取都会导致调用关联的函数。 同样,写操作会调用其他关联的函数。 这些函数导致读取或修改传递给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()完成相同的任务

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM