为什么'$ _'与Perl单行中的$ ARGV相同?

hma*_*tt1 3 bash perl sh

我试图在Perl单行中打印单引号时遇到了这个问题.我最终想通了你必须逃脱它们'\''.这里有一些代码来说明我的问题.

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

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

red
orange
yellow
green
blue
Run Code Online (Sandbox Code Playgroud)

现在让我们为每行打印文件的名称.

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

shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
Run Code Online (Sandbox Code Playgroud)

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

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

shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
shortlist.txt
Run Code Online (Sandbox Code Playgroud)

等等没有用.让我们再试一次.

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

'red'
'orange'
'yellow'
'green'
'blue'
Run Code Online (Sandbox Code Playgroud)

所以我现在就开始工作了.但我仍然对为什么'$ _'评估程序名称感到困惑.也许这很容易,但有人可以解释或链接到一些文档吗?

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

Thi*_*Not 12

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

perl -ne 'chomp; print "'$_'\n"' shortlist.txt
Run Code Online (Sandbox Code Playgroud)

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

$ echo foo
$ perl -ne 'chomp; print "'$_'\n"' shortlist.txt
foo
foo
foo
foo
foo
Run Code Online (Sandbox Code Playgroud)


ike*_*ami 11

对于shell,会'chomp; print "'$_'\n"'产生一个串联的字符串

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

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

chomp; print "shortlist.txt\n"
Run Code Online (Sandbox Code Playgroud)

例如,

$ echo foo
foo

$ echo 'chomp; print "'$_'\n"'
chomp; print "foo\n"
Run Code Online (Sandbox Code Playgroud)


bri*_*foy 5

出于这个原因,我尽量避免在一个衬里中引用.我可以使用广义引用:

% perl -ne 'chomp; print qq($_\n)'
Run Code Online (Sandbox Code Playgroud)

虽然我可以通过-l开关免费获取换行符来避免:

% perl -nle 'chomp; print $_'
Run Code Online (Sandbox Code Playgroud)

如果我不理解单行,我-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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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