2014-06-23 60 views
4

我偶然發現了一些奇怪的Perl字符串解析。這裏有一個例子:用雙冒號在Perl中進行奇數字符串解析

$word = "hello"; 
$test1 = "colon:values::$word:test"; 
$test2 = "colon:values::$word::test"; 

// test1 prints: "colon:values::hello:test" 
// test2 prints: "colon:values::" 

所以,如果Perl的看到兩個冒號在一個字符串變量後,它會(我認爲)想你想使用包名。我想它試圖加載「Hello :: test」並且找不到任何東西 - 因此提前終止了字符串。

這是正常的嗎?我覺得它很違反直覺。我能夠逃脫第一個冒號像這樣來解決它:

$works = "colon:values::$word\::test"; 

這是bug還是我完全失去了一些東西明顯?

+6

總是使用'​​use strict;使用警告;'。這會說你打印了未定義的變量'$ word :: test'。 – ikegami

回答

8

雖然這樣的作品,需要處理的話更廣泛的方式是用大括號來消除歧義的變量名:

perl -E "my $word = 'red'; say qq|colon::values::${word}::test|" 
colon::values::red::test 

這是記錄在perldata

正如一些炮彈,您可以將變量名稱括在 中,以避免字母數字(和下劃線)出現。從以下雙冒號或 撇號插值變量爲一個字符串 獨立的變量名稱時,您 也必須這樣做,因爲這將作爲一個整體進行其他處理 分離:

$who = "Larry"; 
print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n"; 
print "We use ${who}speak when ${who}'s here.\n"; 

無大括號中,Perl會查找$whospeak$who::0$who's變量。最後兩個將是$0$s變量(推測)不存在的包who

3

發生這種情況的原因是因爲它試圖查找$word::test作爲變量名稱。正如您已經正確推導的那樣,包裝分隔符::是名稱的一部分,但它不會遵循$word的值,因爲它不在此處用作符號引用(需要更多語法)。

Oesor的解決方案將解決您的問題 - 解決此類問題的一般方法是使用${identifier}語法。基本上可以在任何時候將變量插入到字符串中使用,並且需要使用有效的標識符字符或相關符號(即::)。

+0

或以前版本的::,\' – ysth

+0

是的,它吸引了很多人。 –

1

Perl使用名稱空間作爲變量名稱,當Perl看到::'時,它使用Perl,它假定以前是包(即名稱空間)名稱。它類似於此錯誤

use strict; 
use warnings; # You're using these? Aren't you? 

my $foo = "bar" 
print "The magic word is $foo_for_you\n"; 

由於下劃線是變量名的有效字符,Perl中假定你想要的變量$foo_for_you_for_you附加價值不$foo。那麼,你會認爲這是一個錯誤功能?它是從這個有什麼區別:

print "The magic word is $foobar\n"; # Whoops! my variable is $foo. 

來解決這個問題是要絕對清楚地表明$foo的方式是你的變量:

print "The magic word is " . $foo . "_for_you\n"; 
printf "The magic word is %s_for_you\n", $foo; 
print "The magic word is ${foo}_for_you\n"; 

,如果你有同樣的問題$foo::for::you(或$foo'for'you)在這種情況下,Perl正在名稱空間foo::for中尋找名爲$you的變量。你可以想像,你可以用類似的解決方案:

print "The magic word is " . $foo . "::for::you\n"; 
printf "The magic word is %d::for::you\n", $foo; 
print "The magic word is ${foo}::for::you\n"; 

命名空間用來幫助保持Perl模塊變量在你的程序修改變量。想象一下,在一個Perl包中調用一個函數,並突然發現你的程序中使用的變量發生了變化。

看看File::Find,你可以看到變量與連接到他們($File::Find::name$File::Find::dir是兩個例子)包命名空間。