我偶然发现了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";
这是一个错误还是我完全错过了一些明显的东西?
答案 0 :(得分:8)
虽然这有效,但处理案例的更广泛的方法是使用大括号消除变量的名称:
perl -E "my $word = 'red'; say qq|colon::values::${word}::test|"
colon::values::red::test
perldata中记录了这一点:
与某些shell一样,您可以将变量名称括在括号中 将其从跟随字母数字(和下划线)中消除歧义。您 在将变量插入到字符串中时,也必须这样做 将变量名称与后面的双冒号或 撇号,因为这些将被视为一个包 分离器:
$who = "Larry"; print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n"; print "We use ${who}speak when ${who}'s here.\n";
没有大括号,Perl会寻找
$whospeak
,a$who::0
和$who's
变量。最后两个是$0
和 (推测)不存在的包$s
中的who
变量。
答案 1 :(得分:3)
之所以发生这种情况,是因为它试图查找$word::test
作为变量名称。如果您已正确推断,则包分隔符::
是名称的一部分,但它不会遵循$word
的值,因为它未被使用作为这里的符号引用(需要更多语法)。
Oesor的解决方案将解决您的问题 - 解决此类问题的一般方法是使用${identifier}
语法。基本上在您将变量插入字符串时使用它,您需要使用有效的标识符或相关符号(即::
)来跟随它。
答案 2 :(得分: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
而不是$foo
并附加_for_you
。那么,你会认为这是 bug 或功能吗?与此有何不同:
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会在命名空间$you
中查找名为foo::for
的变量。您可以想象,您可以使用类似的解决方案:
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
是两个示例)。