简体   繁体   English

将字符串分配给Perl substr?

[英]Assigning a string to Perl substr?

I am looking at Perl script written by someone else, and I found this: 我正在查看别人编写的Perl脚本,发现了这一点:

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

Forgive me ignorance, but for an untrained Perl programmer the second line looks as if the author is assigning the string $num to the result of the function substr . 原谅我的无知,但是对于未经培训的Perl程序员,第二行看起来好像作者正在将字符串$num分配给函数substr的结果。 What does this line exactly do? 这条线到底是做什么的?

Exactly what you think it would do: 正是您认为的那样:

$ perldoc -f substr

You can use the substr() function as an lvalue, in which case EXPR must itself be an lvalue. 您可以将substr()函数用作左值,在这种情况下,EXPR本身必须是左值。 If you assign something shorter than LENGTH, the string will shrink, and if you assign something longer than LENGTH, the string will grow to accommodate it. 如果分配的长度短于LENGTH,则字符串将缩小;如果分配的长度大于LENGTH,则字符串将增长以容纳它。 To keep the string the same length, you may need to pad or chop your value using "sprintf". 为了使字符串长度相同,您可能需要使用“ sprintf”填充或截取值。

In Perl, (unlike say, Python, where strings, tuples are not modifiable in-place), strings can be modified in situ. 在Perl中(不同于Python,字符串,元组不能就地修改),可以在原位修改字符串。 That is what substr is doing here, it is modifying only a part of the string. 这就是substr在这里所做的,它仅修改字符串的一部分。 Instead of this syntax, you can use the more cryptic syntax: 除了这种语法,您还可以使用更隐秘的语法:

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

which accomplishes the same thing. 完成相同的事情。 You can further stretch it. 您可以进一步拉伸它。 Imagine you want to replace all instances of foo by bar in a string, but only within the first 50 characters. 假设您想用字符串中的bar替换foo的所有实例,但只能在前50个字符之内。 Perl will let you do it in a one-liner: Perl将让您一站式完成:

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

Great, isn't it? 很好,不是吗?

"Exactly", you ask? “是的”,您问?

Normally, substr returns a boring string (PV with POK). 通常, 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

However, when substr is evaluated where an lvalue (assignable value) is expected, it returns a magical scalar (PVLV with GMG (get magic) and SMG (set magic)). 但是,当在预期有左值(可分配值)的地方对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

This magical scalar holds the parameters passed to susbtr (TARG, TARGOFF and TARGLEN). 这个神奇的标量保存传递给susbtr的参数(TARG,TARGOFF和TARGLEN)。 You can see the scalar pointed by TARG (the original scalar passed to substr ) repeated at the end (the SV at 0x8948c18 you see at the bottom). 您可以看到在末尾重复了TARG指向的标量(传递给substr的原始标量)(在底部看到的SV在0x8948c18处)。

Any read of this magical scalar results in an associated function to be called instead. 对该神奇标量的任何读取都会导致调用关联的函数。 Similarly, a write calls a different associated function. 同样,写操作会调用其他关联的函数。 These functions cause the selected part of the string passed to substr to be read or modified. 这些函数导致读取或修改传递给substr的字符串的选定部分。

perl -E'
   $_ = "abcde";
   my $ref = \substr($_, 1, 3);  # $$ref is magical
   say $$ref;                    # bcd
   $$ref = '123';
   say $_;                       # a123e
'

Looks to me like it's overwriting the last length($num) characters of $num2 with the contents of $num in order to get a '0' filled number. 在我看来,它用$ num的内容覆盖$ num2的最后一个length($ num)个字符,以便获得一个“ 0”填充数字。

I imagine most folks would accomplish this same task w/ sprintf() 我想大多数人都会用sprintf()完成相同的任务

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

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