我有一个要在命令行中使用perl的-e
选项调试的代码。 (确切地说,是从Mac OS终端上来的)
当我这样调用子例程时,我忘记正确匹配双引号,有点像这样:
perl -e "print lc "Hello-World\n""
#Output: 0
我很惊讶地看到0
,但是在仔细看后,我发现我的双引号有问题。毫不奇怪,使用外部单引号可以解决问题
perl -e 'print lc "Hello-World\n"'
# Output(fixed): hello-world
现在,我知道问题出在哪里,我很高兴看到它首先返回0
。好像bash进行了某种减法运算,因为如果我在那儿没有破折号而重复了同样的错误,即使双引号错误,我也不会遇到这个问题:
perl -e "print lc "HelloWorld\n""
^ closing the quotes too soon
#Output: helloworldn
那么为什么该语法perl -e "print lc "Hello-World\n""
打印0?
答案 0 :(得分:11)
有一个有用的技巧来找出什么是perl在“思考”。
运行perl -MO=Deparse -e "print lc "Hello-World\n""
perl -MO=Deparse -e "print lc "Hello-World\n""
print lc 'Hello' - 'Worldn';
-e syntax OK
这里发生的是perl
在“看到” Hello - Worldn
作为算术和。并且由于字符串在数字上为零,因此您正在打印0-0
。它与bash
无关,而与perl
及其如何处理数字值无关。
这是因为如果您不使用strict
和warnings
,则裸字是可以接受的,但是通过减法(例如0)可以将其强制为数字值
如果您打开了warnings
:
perl -Mwarnings -e "print lc "Hello-World\n""
Argument "Worldn" isn't numeric in subtraction (-) at -e line 1.
Argument "Hello" isn't numeric in subtraction (-) at -e line 1.
答案 1 :(得分:4)
以下内容对于查看由perl解析的代码很有用:
$ perl -MO=Deparse -e "print lc "Hello-World\n""
print lc 'Hello' - 'Worldn';
'Hello'
和'Worldn'
转换为int的值为0。
答案 2 :(得分:2)
在单线内,我倾向于使用generalized quotes来避免这些问题:
$ perl -e "print lc qq(Hello-World\n)"
如果仅在换行符处使用双引号,则可以使用-l
开关向每个print
(但不printf
)添加换行符:
$ perl -le "print lc 'Hello-World'"
使用-E
,您可以启用v5.10功能,包括say
,该功能还会在输出中添加换行符:
$ perl -E "say lc 'Hello-World'"
您已将其标记为macOS
,这意味着您可以对-e
的参数使用单引号(Windows不允许这样做):
$ perl -e 'print lc qq(Hello-World\n)'
$ perl -e 'print lc "Hello-World\n"'
在像shell这样的Unix上的双引号中,以$
开头的是变量。失败是因为Shell在Perl甚至没有看到程序字符串(它是$HOME
)之前就插入print /Users/brian
。这是一个愚蠢的示例,但它显示了问题:
$ perl -le "print $HOME"
Unknown regexp modifier "/b" at -e line 1, at end of line
Unknown regexp modifier "/r" at -e line 1, at end of line
-e had compilation errors.
请转义$
或使用单引号:
$ perl -le "print \$HOME"
$ perl -le 'print $HOME'