提问人:Eugen Konkov 提问时间:5/23/2019 最后编辑:EmmaEugen Konkov 更新时间:5/24/2019 访问量:498
Perl 中 “ 和 ' 的区别
The difference between " and ' in Perl
问:
根据此评论:
也不应在 中使用单引号。 相反,请尝试:
print ">>${ '_<$filename' }<<\n"
print ">>${ \"_<$filename\" }<<\n"
我一直认为 和 之间的区别只是字符串是否被解释。"
'
我想问为什么在这种情况下:
print ">>${ \"_<$filename\" }<<\n"
print ">>${ '_<$filename' }<<\n"
Perl 打印不同的值?
为什么我应该使用而不是在这里?\"
'
答:
在这两种情况下,都不是由外部字符串 () 插值,而是由 插值。(这只是从行为中扣除的)。这意味着 在 中,根本不是插值,而 是 。$filename
">>...<<\n"
${ ... }
">>${ '_<$filename' }<<\n"
$filename
">>${ \"_<$filename\" }<<\n"
如果它是由外部字符串插值的,那么如果你的字符串包含引号,你就会遇到一些麻烦:
$filename = "ab'cd";
如果插值是由外部字符串完成的,则等价于 ,这是一个语法错误。或者更确切地说,是 ,它等价于 ;也不是你想要的。"${'$filename'}"
"${'ab'cd'}"
"${ab'cd}"
"${ab::cd}"
而如果插值是由 完成的,那么 in 是 真的(没有转义的双引号),它插值 ,你会得到类似 的东西,就像你想要的那样。${}
"${'$filename'}"
${...}
${"$filename"}
$filename
${"ab'cd"}
请看这个例子:
$abcd = "First var";
${'$v'} = "Second var";
$v = "abcd";
say "${\"$v\"}"; # prints "First var"
say "${'$v'}"; # prints "Second var"
它表明 with 是插值的,而 with 则不是。"${\"$v\"}"
$v
"${'$v'}"
评论
$filename
Specio::Constraint::Simple->_optimized_constraint
${}
""
$filename
这只是我的假设,我找不到任何关于此的官方文档,但似乎有效。
还说我应该:ilmari
go via the symbol table
${$main::{'_<foo::bar::baz'}}
因此,我的代码分为两种情况:。
案例一:
Devel::Peek::Dump( ${ "::_<$filename" } );
Devel::Peek::Dump( ${ '::_<' ."$filename" } );
Devel::Peek::Dump( ${ "::_<Specio::Constraint::Simple->_optimized_constraint" } );
Devel::Peek::Dump( ${ '::_<Specio::Constraint::Simple->_optimized_constraint' } );
所有这些都是一样的。双引号或单引号:没关系。
SV = PV(0xe64ab00) at 0xe300bc8
REFCNT = 1
FLAGS = ()
PV = 0
案例二:
Devel::Peek::Dump( ${ ${ 'main::' }{ "_<$filename" } } );
Devel::Peek::Dump( ${ ${'::'}{ "_<$filename" } } );
Devel::Peek::Dump( ${ $::{ "_<$filename" } } );
Devel::Peek::Dump( ${ $::{"_<Specio::Constraint::Simple->_optimized_constraint"} } );
Devel::Peek::Dump( ${ $::{'_<Specio::Constraint::Simple->_optimized_constraint'} } );
此外,无论它如何引用,它都有。只需通过符号表,我就可以达到以下值:
SV = PV(0x15e0a40) at 0x186cd10
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x1934880 "Specio::Constraint::Simple->_optimized_constraint"\0
CUR = 49
LEN = 51
发现
它无论如何引用变量名称。唯一的区别在于我们如何去:
- 直接
- VIA 符号表
因此,如果变量名称没有双冒号,则可以使用以下任一形式:
Devel::Peek::Dump( ${ $::{ "$name" } } );
Devel::Peek::Dump( ${ "::$name" } );
两者都会引用同一件事。
但是,如果变量名称包含双冒号,则只能通过符号表访问其值
UPD:
有些人可能会注意到,这个答案并没有直接回答我的问题。你是对的。
我在这里发布了两种不同方法的访问变量值的测试结果,因为我认为这些发现很重要。
评论
\"_<$filename\"
'_<$filename'
${}
$filename
'
Devel::Peek::Dump( ${ '::_<Specio::Constraint::Simple->_optimized_constraint' } );
${ }
对你的问题的简短回答是在你的第一个例子中插入的,而在第二个例子中没有。你问为什么?天啊。系好安全带,享受颠簸的旅程。$filename
首先,了解符号的用途。使用它有两个原因:一是简单地将变量名称与周围的文本区分开来;另一种是取消引用 BLOCK(代码)返回的值。${...}
如果括号的内容只是一个裸词(可能带有空格),那么它只是一个简单的变量名称。因此,字符串、字符串和字符串都产生相同的结果。如果您需要在字符串中的变量之后直接附加文本,这将非常方便:而不是说 ,您可以说 。这些符号在插值字符串之外也起作用:如果你愿意,你可以说。"$foo"
"${foo}"
"${ foo }"
$foo.'bar'
"${foo}bar"
${foo} = 'bar'
但这不是你的代码正在做的事情。哦不。你把象征性去引用的双管霰弹枪直接对准你的脚。您将括号的内容作为代码进行评估,并将结果用作对变量的引用。你把整个地段放在一个插值字符串中,使它加倍混乱。我们不要对取消引用的概念进行深入讨论,因为这不是这里的主要问题。关键的一点是,如果大括号中的内容不是裸词,那么它实际上正在被评估。
现在,要明白,当 Perl 到达插值字符串中的“${”符号时,它必须决定它在这里插值的内容:一个普通的变量名称或代码。在不插入任何其他内容的情况下,它寻求匹配的右括号。如果由这些括号分隔的子字符串看起来不像一个裸词,那么它将被计算。您仍然需要在此区域中转义双引号,因为任何未转义的双引号都将计为作为其子集的外部字符串的最终分隔符,而“块”的其余部分将位于字符串之外。
考虑到这一点,我们可以看到你的第一个示例 evals ,而你的第二个示例 evals 。这就是插值字符串与非插值字符串之间的区别:第一个被某物替换,而第二个是严格意义上的字面意思。"_<$filename"
'_<$filename'
$filename
在这两种情况下,字符串都用于对具有可怕名称的全局标量变量执行符号取消引用,如果您实际定义了它,您将感到羞耻。说得越少越好。
如果您认为我在开玩笑说大括号的内容被有效评估,请尝试此代码。
print "This, ${die qq(oops!\n)}, and this.\n";
当然,像这样的字符串内代码和 proper 之间的主要区别在于,它会捕获异常并设置 $@。这不会:它只是像在普通代码块中一样死亡。eval()
eval()
这就产生了 Perl 的一个隐藏技巧。您不能像 一样插值方法调用,但可以取消引用包含它的数组的引用,如下所示。$foo->bar
print "@{[$foo->bar]}\n";
总而言之,为了上帝的爱,请不要那样写代码。
答案很简单:当在字符串文字的代码中找到 A 和 character 时,没有特别的意义。$
@
">>${ \"_<$filename\" }<<\n"
等效于 。">>" . ${ "_<$filename" } . "<<\n"
">>${ '_<$filename'" }<<\n"
等效于 。">>" . ${ '_<$filename' } . "<<\n"
如您所见,没有替换为 的值,这在双引号字符串中通常会发生。$filename
$filename
如果这还不清楚,让我们考虑一个更常见的例子。
">>$h{$key}<<"
等效于 。">>" . $h{$key} . "<<"
">>$h{\"$key\"}<<"
等效于 。">>" . $h{"$key"} . "<<"
">>$h{'$key'}<<"
等效于 。">>" . $h{'$key'} . "<<"
现在考虑一下如果改为插值会发生什么。(例如,使用 .)这种行为将更加出乎意料,也更加危险。$key
$key = "2+3";
同样,当在字符串文本的代码中找到字符时,除非它转义了分隔符,否则它没有特殊意义。\
"foo ${\f()} bar"
相当于"foo " . ${\f()} . " bar"
如您所见,没有像通常在双引号字符串文本中那样替换为表单提要。\f
评论
"${ \"_<$filename\" }"
$filename