繁体   English   中英

为什么 '$_' 与 Perl one-liner 中的 $ARGV 相同?

[英]Why is '$_' the same as $ARGV in a Perl one-liner?

我在尝试在 Perl 单行中打印单引号时遇到了这个问题。 我最终发现你必须用'\\''来逃避它们。 这是一些代码来说明我的问题。

让我们从打印文本文件开始。

perl -ne 'chomp; print "$_\n"' shortlist.txt

red
orange
yellow
green
blue

现在让我们为每一行打印文件名。

perl -ne 'chomp; print "$ARGV\n"' shortlist.txt

shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt

然后我们可以在每一行周围添加单引号。

perl -ne 'chomp; print "'$_'\n"' shortlist.txt

shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt

等等,没有用。 让我们再试一次。

perl -ne 'chomp; print "'\''$_'\''\n"' shortlist.txt

'red'
'orange'
'yellow'
'green'
'blue'

所以我现在开始工作了。 但我仍然对为什么 '$_' 计算为程序名称感到困惑。 也许这很简单,但有人可以解释或链接到某些文档吗?

编辑:我在 Red Hat 5 上运行 Perl 5.8.8

对你的外壳, 'chomp; print "'$_'\\n"' 'chomp; print "'$_'\\n"'结果是一个字符串的连接

  1. chomp; print " chomp; print " (单引号内的第一个序列),
  2. 其变量$_的值,以及
  3. \\n" (单引号内的第二个序列)。

bash$_ "... 扩展到上一个命令的最后一个参数,扩展后。..."。 由于这恰好是shortlist.txt ,因此将以下内容传递给perl

chomp; print "shortlist.txt\n"

例如,

$ echo foo
foo

$ echo 'chomp; print "'$_'\n"'
chomp; print "foo\n"

请注意,不应使用上述机制将值传递给 Perl 单行程序。 您不应该从 shell 生成 Perl 代码。 请参阅如何在 -n 或 -p 模式下使用 Perl 处理选项? 了解如何为单行提供参数。

您在单行中使用单引号来保护您的 Perl 代码不被 shell 评估。 在这个命令中:

perl -ne 'chomp; print "'$_'\n"' shortlist.txt

您关闭$_之前的单引号,因此 shell 将$_扩展到上一个命令的最后一个参数 在您的情况下,这恰好是您输入文件的名称,但如果您先运行不同的命令,输出会有所不同:

$ echo foo
$ perl -ne 'chomp; print "'$_'\n"' shortlist.txt
foo
foo
foo
foo
foo

正是出于这个原因,我尽量避免在一个班轮中使用引号。 当我可以时,我使用广义引用:

% perl -ne 'chomp; print qq($_\n)'

虽然我可以避免使用-l开关来免费获得换行符:

% perl -nle 'chomp; print $_'

如果我不理解单行,我使用-MO=Deparse来看看 Perl 认为它是什么。 前两个是您期望的:

% perl -MO=Deparse -ne 'chomp; print "$_\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    print "$_\n";
}
-e syntax OK

% perl -MO=Deparse -ne 'chomp; print "$ARGV\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    print "$ARGV\n";
}
-e syntax OK

你在你看到问题的地方看到了一些有趣的东西。 该变量在perl看到它之前就消失了,并且在它的位置有一个常量字符串:

% perl -MO=Deparse -ne 'chomp; print "'$_'\n"' shortlist.txt

LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    print "shortlist.txt\n";
}
-e syntax OK

您的修复也很奇怪,因为Deparse将变量名称放在大括号中以将其与旧的包说明符'分开:

% perl -MO=Deparse -ne 'chomp; print "'\''$_'\''\n"' shortlist.txt
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    print "'${_}'\n";
}
-e syntax OK

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM