在perl中执行命令时使用管道

时间:2013-02-01 11:00:13

标签: perl pipe

我正在尝试在perl中使用以下命令,但它给了我错误

system("zcat myfile.gz | wc > abc.txt");

但是当我运行这个时,我收到了错误 意外标记“|”

附近的语法错误

即使我删除>abc.txt,我仍然会收到错误。

我们可以使用带有系统命令的管道吗?

以下是错误详情:

sh: -c: line 1: syntax error near unexpected token `|'
sh: -c: line 1: ` | wc '

3 个答案:

答案 0 :(得分:5)

下次,测试您的演示程序,确保它实际上展示了您所说的行为。你实际上发现了更接近

的东西
while (my $file_name = <>) {
   system("zcat $file_name | wc > abc.txt");
}

有两个错误:

  • 您没有删除尾随换行符,因此shell正在尝试执行

    zcat def.gz
     | wc >abc.txt
    

    而不是

    zcat def.gz | wc >abc.txt
    
  • 在将命令作为emded之前,您没有将文件名转换为shell文字。

    考虑如果文件名包含空格会发生什么。你将执行

    zcat def ghi.gz | wc >abc.txt
    

    而不是

    zcat 'def ghi.gz' | wc >abc.txt
    

解决方案:

use String::ShellQuote qw( shell_quote );

while (my $file_name = <>) {
   chomp($file_name);
   system("zcat -- ".shell_quote($file_name)." | wc > abc.txt");
}

答案 1 :(得分:1)

它按预期工作:

perl -lne 'system("cat *.java|wc");'

你的文件名可能有些奇怪,可能。

您可以像这样检查shell的插值:

my @file = `ls -1 myfile*.gz`;chomp(@files);
print join("\n",@files);

在perl中还有其他的可能性,比如反引号,用|,qx打开。

如果您遇到文件名问题,可以自己获取文件名并以特定方式调用系统以避免执行shell:http://docstore.mik.ua/orelly/perl/cookbook/ch19_07.htm

  

如果只有一个标量参数,则检查参数是否为shell元字符,如果有,则将整个参数传递给系统的命令shell进行解析(这是Unix平台上的/ bin / sh -c,但在其他平台上有所不同)。如果参数中没有shell元字符,它将被拆分为单词并直接传递给execvp,这样效率更高。

答案 2 :(得分:0)

当尝试使用反引号执行包含cut -d \|命令的管道时,出现此错误消息。原来我不得不对管道字符加倍转义,例如cut -d \\|