【问题标题】:Using pipe when executing command in perl在 perl 中执行命令时使用管道
【发布时间】:2013-02-01 11:00:13
【问题描述】:

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

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

但是当我运行它时,我得到了错误 意外标记 `|' 附近的语法错误

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

我们可以在系统命令中使用管道吗?

以下是错误详情:

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

【问题讨论】:

  • 为我工作。实际的文件名是什么?
  • 我正在尝试给 system("zcat myfile.gz | wc");但它不起作用。
  • 在 solaris 上也适用于我。
  • 其实是它的 myfile*.gz 并且只有一个文件匹配它
  • hmmm 但是我又遇到了同样的错误。有什么办法可以调试吗?

标签: perl pipe


【解决方案1】:

下一次,测试您的演示程序以确保它确实表现出您所说的行为。你实际上跑的更接近

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

其中有两个错误:

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

    zcat def.gz
     | wc >abc.txt
    

    而不是

    zcat def.gz | wc >abc.txt
    
  • 在将文件名嵌入命令之前,您没有将文件名转换为 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");
}

【讨论】:

  • 为什么使用zcat -- 在系统调用中
  • 如果文件名以“-”开头。
【解决方案2】:

它按预期工作:

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 ,这样效率更高。

【讨论】:

  • 像这样检查 shell 的插值是什么意思:
  • 我是 perl 的新手,你能举例说明如何使用 open 或 backtick 或 qx 实现这一目标
【解决方案3】:

我在尝试使用反引号执行包含cut -d \| 命令的管道时收到此错误消息。结果我不得不双重转义管道字符,例如cut -d \\|

【讨论】:

    最近更新 更多