在shell命令中插入perl变量

7

我希望能够从用户那里获取日期作为输入,并将该输入传递给以下Shell命令。

例如:

$date = ARGV[0];
`cd xyz $date`

这个变量会在Perl中进行插值吗?


3
试一试,看看会发生什么! - salva
我不能尝试这些命令,否则这里会变得一团糟,所以为了确认,我想问一下标量变量是否会在带有""的命令中插值。 - Rock
3
你可能不能尝试这些确切的命令,但你可以尝试一个“Hello World”类型的简单例子,而不会出错。 - innaM
4个回答

10
您有几个问题;首先,cd只接受一个参数。也许您想要的是 cd xyz$date? 其次,反引号会启动一个 shell 执行您给出的命令,这将执行更改目录命令,然后立即退出,没有任何效果。(父 perl 进程的当前目录保持不变)。 您可能正在寻找chdir
但是,插值将起作用;要在反引号中禁用插值,您可以转义特殊字符(echo xyz \$date)或使用单引号分隔符的 qx(qx'echo xyz $date')。

9
这很容易测试: 输入:
use v5.16;
use strict;
use warnings;
my $foo = 123;
say `echo $foo`;

输出:

123

是的。

但要注意,变量中包含有特殊意义的字符时需要小心处理。


我建议使用print而不是say,这样就不需要use v5.16。没有use语句,Perl v5.16.3会报错。 - Nagev

6

是的,它将插值变量。但是,我强烈建议两件事:

  • 使用qx/../而不是反引号。
  • 首先将要运行的命令设置为Perl变量,然后插值该变量。

qx/../很好,因为它使你正在做什么更加明显:

my $variable = qx(ls $directory);

你可以使用各种字符来表示qx:
my $variable = qx(ls $directory);
my $variable = qx/ls $directory/;
my $variable = qx^ls $directory^;
my $variable = qx#ls $directory#;
qx 后面的字符将被用作引号。如果您使用圆括号、方括号或花括号,则需要成对使用开放符号和关闭符号。
这意味着您可以避免命令中的特定字符可能会导致混乱的问题。
另一件事是将您的命令构建为 Perl 变量,然后在尝试进行插值时执行它。这样可以更好地控制您正在做的事情:
my $HOME;
my $command;

$HOME = "bin";
$command = "ls $HOME";
print qx($command); #Lists the directory bin

$command = 'ls $HOME';
print qx($command); #List user's home directory

在这两个示例中,我都使用了qx($command)。然而,在第一个示例中,我允许Perl替换$HOME的值。在第二个示例中,我使用单引号,因此Perl不会替换$HOME的值。相反,字符串$HOME只是我正在使用的命令的一部分。我让shell来插入它。
通常情况下,我对任何使用qx/.../的程序都持谨慎态度。在大多数情况下,它被用于运行可以在Perl本身中完成的命令。例如,在早期的Perl程序中,你会看到类似于这样的东西:
 $date = `date +%M/%Y/%D`
 chop $date;     #Yeah, I said EARLY Perl programs

因为直接运行Unix命令比尝试使用纯Perl方法更容易。然而,采用Perl(即正确)的方式意味着您不再依赖于操作系统的行为,这并非完全在您的控制之下。
如果您需要使用命令的输出来执行Perl脚本,则应使用open来执行您的命令,并将命令的输出视为文件。
my $command = "ls $HOME";
open my command_fh, "|-", $command or die qq(Couldn't execute "$command");

如果您只需要执行命令,请使用system命令:
my $command = "xyz $date";
my $error = system $command;
if ( $error ) {
    #Something terrible happened...
}

请注意,如果您仅向system命令发送单个标量参数,并且该参数包含可能的shell元字符,则它将通过OS shell执行该命令。如果您发送要执行的列表给system命令,或者没有shell元字符,则Perl将调用命令执行程序直接执行命令,而不进行任何shell插值:
my @command = qw(ls $HOME);
system @command;   #Will print out "No such directory '$HOME'

@ David W. _ 非常感谢。这对像我这样的新手来说是非常有帮助的信息。 - Rock

6

Perldoc一如既往地提供了答案。

具体而言,http://perldoc.perl.org/perlop.html#Quote-and-Quote-like-Operators在“Interpolates?”列中标注了“Yes”(这里有一个你不必担心的限制条件),因此可以安全地假设您的变量将被插值。

您可以通过在本地命令行中运行“perldoc perlop”来获取相同的文档,通常都可以获得。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接