【问题标题】:why perl -e "print lc "Hello-World\n"" prints 0为什么 perl -e "print lc "Hello-World\n"" 打印 0
【发布时间】:2019-03-19 21:32:03
【问题描述】:

我有一个代码,我想从命令行使用 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 呢?

【问题讨论】:

  • 我不这么认为,但我不想花时间在上面。删除了我的第二条评论,并将很快删除。祝你好运。

标签: bash macos perl


【解决方案1】:

有一个有用的技巧可以找出 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

这里发生的是perlHello - Worldn 视为算术和。由于字符串的数值为零,因此您打印的是0-0。这与bash 无关,而是与perl 以及它如何处理数值有关。

这是因为如果您不使用 strictwarnings,裸字是可以接受的,但会通过减法强制转换为数值(例如 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.

【讨论】:

    【解决方案2】:

    下面的内容对于查看 perl 解析的代码很有用:

    $ perl -MO=Deparse -e "print lc "Hello-World\n""
    print lc 'Hello' - 'Worldn';
    

    'Hello''Worldn' 转换为int 为0。

    【讨论】:

    • 这真的很有用。 +1 - 但它没有回答问题
    • 为什么这不能回答问题,接受的答案是同样的事情
    • 这不仅仅是“同一件事”。它详细说明了为什么 hello 被转换为 0。它解释了为什么我错误地认为它是一种 bash 行为以及它实际上是如何执行的。它还引入了关键字“bareword”并添加了警告细节。请参阅 - 对于 Perl 的新手来说,这些细节决定了复制粘贴答案还是理解答案
    【解决方案3】:

    在单行中,我倾向于使用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"'
    

    在类 Unix shell 的双引号内,以 $ 开头的东西是变量。这失败了,因为 shell 在 Perl 甚至看到程序字符串(它是 print /Users/brian)之前插入了 $HOME。这是一个愚蠢的例子,但它说明了问题:

     $ 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'
    

    【讨论】:

      猜你喜欢
      • 2016-06-01
      • 2020-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-20
      • 2015-12-04
      • 2018-10-31
      相关资源
      最近更新 更多