在反引号命令中使用管道

时间:2012-12-10 12:42:42

标签: perl

我遇到了一些代码问题,我想知道是否有人可以提供帮助。

基本上我正在尝试对数据库执行isql查询并将其分配给标量变量。 isql命令使用列分隔符,该分隔符定义为管道符号。

所以我这样设置:

my $command = "isql -S -U -s| -i";
my $isql_output = `$command`;

isql命令在隔离状态下工作,但在作为反引号发出时,它会在管道处停止。我尝试使用子字符串连接$command字符串,使用单引号和反斜杠转义-s\"\|\"之类的项目无济于事。我也尝试使用qx而不是反引号。

不幸的是,我目前正在使用较旧版本的perl(v5.6.1),升级范围有限,所以我不确定是否可以解决此问题。

3 个答案:

答案 0 :(得分:4)

您必须引用|,使shell不会将其识别为特殊字符。两种方式:

  1. -s|放入单引号:'-s|'。 Perl将单引号放在双引号字符串中,并将它们未经修改地传递给shell。
  2. 使用两个反斜杠逃离|-s\\|。为什么两个?第一个是Perl看到它告诉它通过未经修改的下一个字符。因此,shell会看到-s\|并执行非常相似的操作:它会看到单个\,并且知道不会处理下一个字符|,特殊。

答案 1 :(得分:1)

问题是该命令是通过shell执行的。 您可以通过在列表而不是单个字符串中传递命令和参数来避免这种情况。 反引号构造不支持,因此您需要使用open()函数。 我没有测试过以下代码,但它提出了这个想法:

my @command = (qw(isql -Sserver -Uuser -Ppassword -s| -w4096), '–i' . $file);
print join(' ', @command), "\n";
open(my $fh, '-|', @command)
  or die "failed to run isql command: $@\n";
my @isql_output = <$fh>;
close($fh);
my $isql_output = $isql_output[0]; chomp($isql_output);

如果您正在使用15年前版本的Perl(Oracle用户倾向于这样做),我不确定这一切都会得到支持。例如,您可能需要编写chop而不是chomp

更新:问题不在于Perl版本,但在Windows according to the documentation上不支持此构造。这必须是合格的:我在Cygwin上使用Perl并且在那里工作正常,但我不知道你是否可以使用Cygwin。

答案 2 :(得分:0)

单引号应该有效。尝试运行测试perl脚本:

my $cmd = "./test.sh -S -U -s '|' -i";
print `$cmd`;

使用test.sh:

#!/bin/sh

echo $@

输出应为-S -U -s | -i