我在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还是我完全忽略了一些明显的东西?
3条答案
按热度按时间cedebl8k1#
虽然这样做是可行的,但更普遍的处理方法是用大括号消除变量名称的歧义:
这在perldata中有记录:
在一些shell中,你可以用大括号将变量名括起来,以区分它与后面的字母数字(和下划线)。在将变量插入到字符串中时,你也必须这样做,以将变量名与后面的双冒号或撇号分隔开,因为否则它们将被视为包分隔符:
如果没有大括号,Perl将查找
$whospeak
、$who::0
和$who's
变量,最后两个变量将是(可能)不存在的包who
中的$0
和$s
变量。pexxcrt22#
发生这种情况的原因是因为它试图将
$word::test
作为变量名来查找,正如您所正确推断的,包分隔符::
是变量名的一部分,但它不会跟随$word
的值,因为它在这里没有被用作符号引用(这需要更多语法)。Oesor的解决方案可以解决你的问题--解决这类问题的一般方法是使用
${identifier}
语法。基本上,当你在字符串中插入一个变量,并且你需要在它后面跟一个有效的标识符字符或相关符号(例如::
)时,可以使用它。kiayqfof3#
Perl使用命名空间作为变量名,当Perl看到
::
或一个'
时,它会假设前面的是一个包(即命名空间)名。由于下划线是变量名的有效字符,Perl假设您需要变量
$foo_for_you
,而不是$foo
,并将_for_you
附加到值上。那么,您认为这是一个 bug 还是一个 feature?解决这个问题的方法是绝对明确地说明
$foo
是您的变量:同样的问题,如果你有
$foo::for::you
(或$foo'for'you
)在这种情况下,Perl正在寻找一个名为$you
的变量在命名空间foo::for
中。命名空间用于防止Perl模块中的变量修改程序中的变量。想象一下,调用Perl包中的函数,突然发现程序中使用的变量被更改了。
看看File::Find,您可以看到附加了包名称空间的变量(
$File::Find::name
和$File::Find::dir
是两个示例)。