2012-09-10 114 views
1

我在看別人寫的Perl腳本,我發現這一點:爲Perl substr分配一個字符串?

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

原諒我的無知,但對未經訓練的Perl程序員第二行看起來好像筆者分配字符串$num到功能substr的結果。這條線究竟幹什麼?

回答

4

在Perl中,(不像說,巨蟒,其中字符串,元組是不是就地修改),字符串可以就地進行修改。這就是substr在這裏所做的,它只修改字符串的一部分。代替這種語法,您可以使用更隱蔽的語法:

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

它完成相同的事情。你可以進一步拉伸它。想象一下,你想用代替foo的所有實例,但只在前50個字符內。 Perl會讓你在一行中做到這一點:

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

很好,不是嗎?

+1

你甚至可以使用負位置:'SUBSTR($ NUM2,-length($ NUM),長度($ NUM),$ NUM)' – choroba

+0

是的,當然。 – SexyBeast

+0

並且由於substr擴展到最後,所以它可以寫成:substr($ num2,-length($ num))= $ num'。 (只要你知道長度($ num)不是0) – ysth

6

正是你認爲它會做的事:

$ perldoc -f substr 

您可以使用SUBSTR()函數作爲左值,在這種情況下 EXPR本身必須是一個左值。如果您指定的內容長度比LENGTH短 ,字符串將縮小,並且如果將 分配的內容長於LENGTH,字符串將增長爲 。要保持字符串的長度相同,您可能需要使用「sprintf」填充或切斷您的值。

1

在我看來,它是用$ num的內容覆蓋$ num2的最後一個長度($ num)字符以獲得一個'0'填充數字。

我想大多數人會完成這個相同的任務瓦特/ sprintf的()

2

「正是」,你問?

通常,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評估,它返回一個神奇的標量(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 
' 
相關問題